
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Replace port numbers with stable, named .localhost URLs. For humans and agents.
Attribution: trulocal is a rebrand/adaptation of the original portless project by Vercel Labs.
Replace port numbers with stable, named .localhost URLs. For humans and agents.
- "dev": "next dev" # http://localhost:3000
+ "dev": "trulocal myapp next dev" # Windows: http://myapp.localhost | Unix: http://myapp.localhost:1355
# Install
npm install -g trulocal
# Start the proxy (once, no sudo needed)
trulocal proxy start
# Run your app (auto-starts the proxy if needed)
trulocal myapp next dev
# -> Windows: http://myapp.localhost
# -> macOS/Linux: http://myapp.localhost:1355
The proxy auto-starts when you run an app. You can also start it explicitly with
trulocal proxy start.
Local dev with port numbers is fragile:
EADDRINUSElocalhost bleed across apps on different ports; localStorage is lost when ports shift.env files all break when ports changelocalhost:3000 is a jumble of unrelated projectstrulocal fixes all of this by giving each dev server a stable, named .localhost URL that both humans and agents can rely on.
# Basic
trulocal myapp next dev
# -> Windows: http://myapp.localhost
# -> macOS/Linux: http://myapp.localhost:1355
# Subdomains
trulocal api.myapp pnpm start
# -> Windows: http://api.myapp.localhost
# -> macOS/Linux: http://api.myapp.localhost:1355
trulocal docs.myapp next dev
# -> Windows: http://docs.myapp.localhost
# -> macOS/Linux: http://docs.myapp.localhost:1355
{
"scripts": {
"dev": "trulocal myapp next dev"
}
}
The proxy auto-starts when you run an app. Or start it explicitly: trulocal proxy start.
For monorepos, you can generate a local script that ensures trulocal is used consistently across all apps:
trulocal init
This creates scripts/trulocal.js. You can then use it in your package.json scripts:
{
"scripts": {
"dev:web:trulocal": "node scripts/trulocal.js myapp bun run dev:web"
}
}
flowchart TD
Browser["Browser\nmyapp.localhost[:port]"]
Proxy["trulocal proxy\n(default: Windows 80, Unix 1355)"]
App1[":4123\nmyapp"]
App2[":4567\napi"]
Browser -->|default proxy port| Proxy
Proxy --> App1
Proxy --> App2
trulocal proxy starttrulocal <name> <command> assigns a free port and registers with the proxyhttp://<name>.localhost on Windows (default port 80), or http://<name>.localhost:1355 on macOS/Linux. With --https, Windows defaults to port 443 for clean https:// URLs.Apps are assigned a random port (4000-4999) via the PORT environment variable. Most frameworks (Next.js, Vite, etc.) respect this automatically.
Enable HTTP/2 for faster dev server page loads. Browsers limit HTTP/1.1 to 6 connections per host, which bottlenecks dev servers that serve many unbundled files (Vite, Nuxt, etc.). HTTP/2 multiplexes all requests over a single connection.
# Start with HTTPS/2 -- generates certs and trusts them automatically
trulocal proxy start --https
# First run prompts for sudo once to add the CA to your system trust store.
# After that, no prompts. No browser warnings.
# Make it permanent (add to .bashrc / .zshrc)
export TRUELOCAL_HTTPS=1
trulocal proxy start # HTTPS by default now
# Use your own certs (e.g., from mkcert)
trulocal proxy start --cert ./cert.pem --key ./key.pem
# If you skipped sudo on first run, trust the CA later
sudo trulocal trust
trulocal <name> <cmd> [args...] # Run app at http://<name>.localhost (Windows) or :1355 (Unix)
trulocal list # Show active routes
trulocal trust # Add local CA to system trust store
trulocal init # Create a local script for monorepos
# Disable trulocal (run command directly)
TRUELOCAL=0 pnpm dev # Bypasses proxy, uses default port
# Also accepts TRUELOCAL=skip
# Proxy control
trulocal proxy start # Start proxy (Windows HTTP: 80, HTTPS: 443; Unix: 1355)
trulocal proxy start --https # Start with HTTP/2 + TLS (Windows: port 443)
trulocal proxy start -p 80 # Start on port 80 (Unix may require sudo)
trulocal proxy start --foreground # Start in foreground (for debugging)
trulocal proxy stop # Stop the proxy
# Options
-p, --port <number> # Port for the proxy (Windows HTTP:80/HTTPS:443, Unix: 1355)
# On Unix, ports < 1024 require sudo
--https # Enable HTTP/2 + TLS with auto-generated certs
--cert <path> # Use a custom TLS certificate (implies --https)
--key <path> # Use a custom TLS private key (implies --https)
--no-tls # Disable HTTPS (overrides TRUELOCAL_HTTPS)
--foreground # Run proxy in foreground instead of daemon
# Environment variables
TRUELOCAL_PORT=<number> # Override the default proxy port
TRUELOCAL_HTTPS=1 # Always enable HTTPS
TRUELOCAL_STATE_DIR=<path> # Override the state directory
PORTLESS_* # Legacy env vars still supported
# Info
trulocal --help # Show help
trulocal --version # Show version
trulocal stores its state (routes, PID file, port file) in a directory that depends on the proxy port:
/tmp/trulocal -- shared between root and user processes~/.trulocal -- user-scoped, no root involvement%TEMP%\trulocal or %USERPROFILE%\.trulocal (same logic applies)Override with TRUELOCAL_STATE_DIR (or legacy PORTLESS_STATE_DIR) if needed.
If https://api.myapp.localhost works but https://myapp.localhost shows a privacy warning, the issue is usually hostname/SAN mismatch, stale cert cache, or stale proxy state.
Use this checklist:
# 1) Restart proxy cleanly
trulocal proxy stop
trulocal proxy start --https
# 2) Inspect served cert for the failing hostname
openssl s_client -connect 127.0.0.1:443 -servername myapp.localhost 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
# 3) Re-trust the local CA (safe to re-run)
trulocal trust
Expected: SAN output includes the exact hostname (for example DNS:myapp.localhost).
Implementation detail: trulocal generates per-host SNI certificates for all non-localhost hostnames. This avoids browser edge cases with wildcard *.localhost matching and applies to any app name.
trulocal proxy start listens on port 80 by default, so apps are available as http://myapp.localhost (no :port suffix). With --https, the default switches to port 443 for clean https://myapp.localhost URLs.sudo, Windows uses "Run as Administrator". Where Unix uses lsof, Windows uses netstat -ano. Where Unix uses kill, Windows uses taskkill /PID <pid> /F.trulocal trust command uses certutil to add the CA to the Windows certificate store. This may prompt for Administrator access..localhost domains to 127.0.0.1.trulocal trust command adds the CA to your login keychain. No sudo required -- the OS shows a GUI authorization prompt..localhost domains auto-resolve to 127.0.0.1 on modern macOS.trulocal trust command requires sudo to copy the CA to /usr/local/share/ca-certificates/ and run update-ca-certificates..localhost domains auto-resolve to 127.0.0.1 on modern Linux distributions.FAQs
Replace port numbers with stable, named .localhost URLs. For humans and agents.
We found that trulocal demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.