Portle is a mixed-language monorepo with a Go runtime/proxy core and an npm distribution wrapper.
.
├── go/portle # Go core binary (`portle`)
│ ├── cmd/portle # CLI entrypoint
│ └── internal # config, IPC, leader, proxy, runtime
├── packages/npm # npm package wrapper + CLI shim
│ ├── bin/portle.js # ESM CLI shim
│ ├── scripts/postinstall.js
│ ├── src # platform mapping + downloader helpers
│ └── test # Node tests
├── scripts/check-gofmt.sh
└── .github/workflows/ci.yml
npm ci --ignore-scriptsnpm run lint
npm run format:check
npm run testcd go/portle
go run ./cmd/portle devCustom wrapped command:
go run ./cmd/portle dev -- pnpm dev- CLI flags:
--name,--port package.json→portle.name/portle.portpackage.jsonroot →name/port- Framework first-match defaults (Next, Vite, Nuxt, SvelteKit, Astro, Remix)
- Random free port in
3000-6000; fallback to OS ephemeral
- Spawns wrapped subprocess (
npm run devby default, or command after--) - Injects environment variables:
PORTPORTLE_NAME
- Connects to IPC leader (or becomes leader if none is available)
- Registers
host -> {port, pid, lastSeen} - Sends heartbeats
- Unregisters on shutdown
- Owns in-memory host registry
- Hosts IPC server for register/heartbeat/unregister JSON-line messages
- Hosts reverse proxy (
127.0.0.1:8080by default) - Routes by request
Hostheader tolocalhost:<port> - Returns
502for unknown hosts
- macOS/Linux: Unix socket at
/tmp/portle.sock - Windows: named pipe at
\\.\\pipe\\portle
Message types:
register {host, port, pid}heartbeat {pid}unregister {host, pid}
packages/npm contains an ESM wrapper package (portle) with:
bin/portle.jsshim that resolves and spawns the downloaded binarypostinstallscript that downloads release assets named:portle-darwin-arm64portle-darwin-x64portle-linux-x64portle-windows-x64.exe
Release URL pattern:
https://github.com/shellscape/portle/releases/download/v<version>/portle-{os}-{arch}[.exe]
- Release publishing automation is not included here (only download-time conventions are implemented).
- Leader failover is best-effort and local-process based (no external persistence).