lpm proxy
Route local HTTPS hostnames to development services and manage the proxy daemon.
lpm proxy manages the local daemon that routes names such as app.localhost to your development services.
lpm proxy [ACTION] [--detach] [--http-port <PORT>] [--tls-port <PORT>] [--http-redirect-port <PORT>] [--privileged-ports] [--replace] [--json]The proxy terminates HTTPS and forwards requests to a plain HTTP application. Use it for stable local hostnames, multiple services, and WebSocket or HMR connections.
| Action | Purpose |
|---|---|
status | Show the daemon, listeners, and routes. This is the default. |
list | Show active routes. |
start | Run the daemon in the foreground, or use --detach for the background. |
stop | Stop the current daemon. |
install | Install and start a persistent service for the current user. |
uninstall | Remove the persistent user service. |
Quickstart with lpm.json
Configure an HTTPS port that does not require administrator privileges:
{
"$schema": "https://cli.lpm.dev/schemas/lpm.json",
"proxy": {
"host": "app.localhost",
"port": 9443,
"httpRedirect": false
}
}lpm devlpm dev starts the proxy if necessary, prepares certificates, and registers the hostname against the assigned application port.
Open https://app.localhost:9443. LPM CLI skips hosts-file edits for .localhost names. Name resolution depends on your browser and operating system.
For a non-interactive run that needs initial CA trust consent:
lpm dev --yesOperating-system authentication can still be necessary. See lpm cert for machine setup.
Examples
lpm proxy
lpm proxy list
lpm proxy start --detach --tls-port 9443 --json
lpm proxy start --tls-port 9443 --http-redirect-port 9080
lpm proxy start --http-port 8080
lpm proxy install --tls-port 9443
lpm proxy install --privileged-ports
lpm proxy stop --json
lpm proxy uninstall --privileged-portsRoute multiple services
{
"proxy": {
"port": 9443,
"httpRedirect": false
},
"services": {
"web": {
"command": "vite",
"port": 5173,
"host": "web.localhost"
},
"api": {
"command": "node api.js",
"port": 4000,
"host": "api.localhost"
}
}
}lpm dev
lpm proxy listEach hostname routes to the assigned port for its service. The route table includes the hostname, project directory, service, and upstream port.
proxy.host applies to the sole service or the unique service with primary: true. Multiple services without a unique primary cannot share this shortcut.
When the development session exits, LPM CLI releases its routes. The shared proxy can continue to serve other projects.
Select listeners
With no listener flags, start and install read lpm.json from the project: the nearest directory at or above the current one that has a package.json or an lpm.json, stopping before your home directory. They print that directory when it is not the current one. Other actions don't read the project.
| Configuration | Listeners |
|---|---|
| At least one configured hostname | HTTPS uses proxy.port, or 443 by default. HTTP redirect uses 80 unless proxy.httpRedirect is false. |
| No configured hostname | Only the control endpoint starts. |
| Any explicit listener flag | Only the specified listeners start. Configuration does not supply additional listeners. |
A privileged installation has separate defaults described in Persistent services.
Listener addresses bind to 127.0.0.1. Port 0 lets the operating system assign a port:
lpm proxy start --detach --tls-port 0 --jsonUse status to read the assigned address. lpm dev startup output and the development dashboard include the actual HTTPS port.
Redirect HTTP to HTTPS
lpm proxy start --tls-port 9443 --http-redirect-port 9080--http-redirect-port requires --tls-port in the same invocation. The redirect preserves the request path and query.
For a direct listener, redirects use its HTTPS port. For a privileged forwarder, redirects use the public HTTPS port.
Change existing listeners
A detached start reuses a running daemon. It does not change that daemon's listeners.
lpm proxy status
lpm proxy stop
lpm proxy start --detach --tls-port 9443If a persistent service owns the daemon, reinstall the service with the new listener configuration. A service manager can restart a daemon after stop.
Configured hostnames require HTTPS. A control endpoint or a plain HTTP listener alone cannot serve the hostname workflow in lpm dev.
Install a persistent service
lpm proxy install --tls-port 9443Installation starts the service and records the project directory as its working directory. Reinstallation applies the new listener configuration.
| Platform | Service |
|---|---|
| macOS | User LaunchAgent. |
| Linux | systemd user service. |
| Windows | Logon Scheduled Task. |
On Linux and macOS, user services reject ports 1–1023. Use a high port or the privileged forwarder.
Use public ports 443 and 80
On Linux or macOS, run this command as the target user:
lpm proxy install --privileged-portsDo not prefix the full command with sudo. LPM CLI requests elevation for the root-owned forwarder.
The installation creates a user proxy and a root-owned loopback forwarder. Without explicit listener flags, public HTTPS uses 443, including projects with a high proxy.port.
The forwarder runs a root-owned copy of LPM CLI. The installation puts the copy in this directory:
| Platform | Directory |
|---|---|
| macOS | /Library/Application Support/LPM/Forwarder |
| Linux | /opt/lpm/proxy-forwarder |
The copy is the LPM CLI that you used for the installation. On macOS, the installation makes sure that the copy has the code signature of that build. The LPM CLI app bundle must also have the Developer ID signature of LPM.
If a user other than root can change a directory on the path to the copy, the installation stops. The same rule applies to the configuration file and the service file of the forwarder. Other users can get write access through directory permissions or an access control list. On a volume that ignores ownership, all users can change all files. By default, macOS mounts external drives in this mode.
When you update LPM CLI, the copy does not change. After each update, run lpm proxy install --privileged-ports again. If the forwarder runs an older version, lpm proxy status shows a warning.
The public HTTP redirect uses 80 unless proxy.httpRedirect is false. This opt-out also applies before a hostname is configured.
Each time the user proxy starts, it uses free loopback ports for its backends. The forwarder sends connections to these ports. If another program uses a port that the proxy used before, the service continues to run. Browser URLs and redirects use the public port.
An installation from an earlier release keeps its fixed backend ports and runs your own LPM CLI as root. lpm proxy status shows a warning for this installation. To update it, run lpm proxy install --privileged-ports again.
To select different public ports, provide explicit low ports:
lpm proxy install --privileged-ports --tls-port 444 --http-redirect-port 81The forwarder supports HTTPS and HTTP redirects. Plain --http-port forwarding is unavailable.
If another user owns the forwarder, installation stops. To replace that user's forwarder explicitly:
lpm proxy install --privileged-ports --replaceRemove a persistent service
lpm proxy uninstallTo remove both the user service and its privileged forwarder:
lpm proxy uninstall --privileged-portsThe command refuses to remove another user's forwarder. Service-manager failures return an error. Inspect the reported failure before retrying cleanup.
Uninstallation does not remove project certificates or managed hosts-file entries.
Certificates and hostnames
The proxy selects the project certificate from the HTTPS hostname. Route registration prepares or refreshes that certificate.
The proxy daemon does not install CA trust. lpm dev handles certificate consent, or you can run lpm cert trust during setup.
Keep the application behind the proxy on plain HTTP. Framework HTTPS conflicts with this workflow.
Hostnames must be distinct, valid multi-label names. LPM CLI normalizes case and surrounding whitespace.
Local suffixes include .localhost, .local, .test, .internal, and .home.arpa. Public names require cert.allowPublicDns in lpm.json.
For names outside .localhost, lpm dev can request permission to add managed hosts-file entries. Normal shutdown removes the session's block.
After an interrupted session, use lpm hosts clean:
lpm hosts cleanProxy start and stop do not manage those entries. lpm dev --https uses a separate HTTPS frontend for development without hostname routes.
Status, JSON, and recovery
lpm proxy status --json
lpm proxy list --json
lpm proxy start --detach --tls-port 9443 --jsonstatus, list, and detached start return the same status envelope. Human list output shows only routes.
| JSON field | Meaning |
|---|---|
running, pid | Whether the daemon responds and its process ID. |
httpAddr, httpRedirectAddr, tlsAddr | Bound listener addresses, or null. |
public_tls_addr | Public HTTPS address for an installed forwarder, or null for a direct listener. |
routes | Active hostname routes. |
stale, stateError | Saved state that does not describe a reachable daemon, and any state error. |
If stale is true, saved addresses can remain present. running is false, and no routes are active.
Foreground start --json is unsupported. Use detached startup, or inspect the daemon from another terminal.
If a hostname fails, inspect the listeners and route table:
lpm proxy status
lpm proxy list
lpm cert statusIf the listener configuration differs, stop or reinstall the daemon with the required ports. If a route is absent, restart the relevant development session.
Flags
| Flag | Actions | Effect |
|---|---|---|
--detach | start | Start in the background and wait for readiness. |
--http-port <PORT> | start, install | Enable plain HTTP. |
--tls-port <PORT> | start, install | Enable HTTPS. |
--http-redirect-port <PORT> | start, install | Enable HTTP redirects. Requires --tls-port. |
--privileged-ports | install, uninstall | Install or remove the Unix forwarder for low ports. |
--replace | install --privileged-ports | Replace another user's forwarder. |
--json | All except foreground start | Print machine-readable output. |
Invalid action/flag combinations fail before the operation. See global flags for shared options.