Plain HTTP on localhost breaks things. OAuth callbacks want https://, Secure cookies won't set, service workers won't register, and some SDKs just assume TLS. Self-signed certs get you back to the "Proceed (unsafe)" click. mkcert solves the cert half well, but it stops at handing you a .pem and a key — you still wire that into every dev server and track which port is which.
mkdev sits one layer up. You give a route a name, you get trusted HTTPS at that name.
mkdev install # generate a local CA, trust it in the system store
mkdev add myapp localhost:3000 # https://myapp.local → localhost:3000
mkdev serve # run the TLS proxy
curl https://myapp.local # 200, no warnings
How it works
mkdev is a TLS reverse proxy, not a cert file generator. That distinction is the whole design.
On install it generates an ECDSA P-256 root CA at ~/.mkdev/ca/ (private key written 0o400, owner-read only) and installs it into the OS-native trust store. The trust-store integration — Keychain via security on macOS, the CA-bundle dirs plus update-ca-* on Linux, the ROOT store via crypt32.dll on Windows — is adapted from mkcert (BSD-3, credited in LICENSE-MKCERT). That layer is the genuinely OS-specific part and reusing it saved a lot of pain.
add <name> <target> does two things: writes the route to a bbolt KV at ~/.mkdev/state.db, and appends 127.0.0.1 myapp.local to /etc/hosts so the name resolves. The hosts write is privileged, so the binary re-invokes itself under sudo through a hidden hosts-helper subcommand that edits the file atomically.
serve binds TLS on 0.0.0.0:443 and, for each incoming SNI hostname, mints a leaf cert on demand signed by the root CA, then reverse-proxies the decrypted request to the mapped host:port. Your dev server keeps speaking plain HTTP and never knows. The route table is re-read every 2 seconds, so add and remove take effect without restarting the proxy — no IPC needed between the CLI and the running server.
<target> accepts host:port, or a full http:///https:// URL with a path. HTTPS upstreams (say, a private GitLab on a VPN) must verify against the system trust store like anything else.
Sharing over the LAN
Since the proxy already binds 0.0.0.0 and mints per-hostname certs, advertising a route over mDNS is cheap. In the TUI, select a route and press s to mark it shared. That myapp.local gets broadcast to the local network pointing at your LAN IP, so a phone or a teammate's laptop on the same Wi-Fi can load it over real HTTPS — useful for testing mobile layouts on an actual device.
The default is closed. Even though the proxy binds 0.0.0.0, a connection-source ACL 403s any non-loopback request to a route not explicitly marked shared. Loopback always passes. Caveats: only .local routes are advertised, multicast is often blocked on corporate/cloud networks, and anyone on the LAN can reach a shared route — don't enable it on untrusted Wi-Fi. Remote devices also need to trust the mkdev CA to connect cleanly.
Known limits
-
Firefox uses its own NSS store and ignores system trust, so it warns until you import
~/.mkdev/ca/rootCA.pemmanually. Chrome, Safari, Edge,curl, andwgetwork out of the box. NSS integration is on the roadmap. -
Port 443 needs root. If that's too much friction, set
proxy_port = 8443in~/.mkdev/config.tomland usehttps://myapp.local:8443without sudo. -
The sudo cache expires (~5 min), so
mkdev addmay re-prompt. The TUI elevates viaosascript(macOS) orpkexec(Linux) instead.
Install
Single binary for macOS (Intel + Apple Silicon), Linux (amd64 + arm64), and Windows.
brew install venkatkrishna07/tap/mkdev
# or
go install github.com/venkatkrishna07/mkdev/cmd/mkdev@latest
mkdev install
mkdev # launches the TUI
MIT-licensed.





















