On this page
These are the ideas planned for after v0.1.
Note: Nothing on this page is built yet, and the details may change. Each item needs an update to the spec before work starts. Items that change lokal’s security requirements also need explicit sign-off.
Feedback is welcome. If one of these would help you, or you’d design it differently, open an issue.
lokal.toml and lokal up: one command starts a repo’s whole stack#
Why. A teammate or a coding agent should get a repo’s dev servers running behind their domains with one
command and no port archaeology. The repo commits one file, and lokal up routes every service and starts its dev
server.
# lokal.toml at the repo root
project = "shop" # optional; default: the directory name
[services]
"@" = { run = "npm start", port = 3000 } # https://shop.lokal, fixed port
api = { run = "cargo run -p api", cwd = "services/api" } # lokal picks a free port
web = { run = "vite --port {port}", host_header = "upstream" }
docs = "mkdocs serve -a 127.0.0.1:{port}" # short form: the string is the commandSketch.
- Every service has a
runcommand. Servers that lokal doesn’t start (a container, something started by hand) stay withlokal service add. lokal upcreates the project, picks ports, and routes every service in one reload, so every URL is live before any command starts. It then runs the commands in the foreground with prefixed, interleaved output. Ctrl-C stops them all.- Each command gets
PORT,{port}substitution, its own URL inLOKAL_URL, and every other service’s URL (LOKAL_URL_API=https://api.shop.lokal), so services can call each other by name. - Each service’s output also goes to a log file that
lokal logs <service>reads. - Trust prompt.
lokal upruns commands from a file in someone else’s repo. So the first run, and any run after the file changes, lists the commands and asks before running them.--yesskips the prompt. lokal downremoves the routes thatlokal upadded.
LAN mode: open your dev URLs on a phone#
Why. Test https://api.shop.local on a real phone on the same Wi-Fi, with a valid certificate.
Sketch.
- Opt-in per project (
lokal lan on -p shop), off by default, and clearly shown instatusanddoctor. - Publish the opted-in names on the real network interfaces with the Mac’s LAN addresses, and accept connections on the LAN address only for those names.
lokal lan profilewrites a configuration profile with the CA for iOS (Android needs a user CA). The CA’s name constraints still limit what it can sign to.lokaland.local.- This changes the “listeners are loopback-only” rule, so it needs a security review first. Open questions include pairing or client allowlists, and warnings on untrusted networks.
lokal run <service> -- <command>: no port numbers at all#
Why. Choosing and wiring port numbers is the last manual step. lokal run web -- npm run dev should give you
https://web.<project>.lokal with nothing else to set up.
Sketch. lokal picks a free port, routes the service to it, and runs the command with PORT=<port> (and a
{port} placeholder for servers that ignore PORT). The exit code is the command’s. It’s the one-off form of
lokal up, without a file, so it’s built on the same code afterwards.
Error trips: show the coding agent where an error started#
Why. When several services run together, the service that shows an error is rarely the one that caused it.
lokal sits in the request path and, with lokal up, owns every process’s output. So it can show the whole trip
of a failing request and name the service where it started.
error trip req a1f3 (412 ms)
console.shop.lokal GET /billing → 500 shows "something went wrong"
└─ api.shop.lokal GET /v1/invoices → 500 "upstream auth failed"
└─ auth.shop.lokal POST /introspect → 401 ← origin
auth | token audience mismatch: expected "api", got "console" src/verify.ts:88Principles.
- lokal captures and correlates. The coding agent diagnoses. There’s no model inside lokal.
- Everything stays on the machine: no account, no collector, no required instrumentation.
- Built in small steps, each useful on its own: per-service logs (from
lokal up, above), recorded proxy hops with W3Ctraceparent, alokal events --errors --jsoncommand for agents, request replay with credentials redacted, and later an OpenTelemetry receiver. - Recording requests touches credentials and customer data, so this needs a security review first: local-only,
0600 files, short retention, and
AuthorizationandCookieredacted by default.
lokal share: public URLs for a dev stack, through Cloudflare Tunnel#
Why. Show a running stack to a reviewer, QA, a client or a webhook provider without deploying it.
Sketch.
- You bring your own Cloudflare account.
lokal share --setupconnects it and picks a zone and base name (dev.example.com). lokal share api webrunscloudflaredwith one rule per shared service, pointing at lokal’s proxy with TLS verification on. Ctrl-C stops sharing and removes the tunnel and its hostnames.- Sharing is always explicit, per command. Nothing is public by default, and lokal’s own listeners stay
loopback-only, because
cloudflareddials out. - Credentials are stored in the macOS keychain. Public exposure needs a security review first.
Smaller items#
- Upstream HTTPS: proxy to dev servers that only speak HTTPS.
service enableandservice disable: keep a service configured but stop serving it.- Shell completions for zsh, bash and fish.
- Linux support: the platform seam is ready.
PORTING.mdcollects what each OS needs.