portless 0.5.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +104 -130
- package/dist/{chunk-P3DHZHEZ.js → chunk-Y6FWHU6F.js} +158 -39
- package/dist/cli.js +360 -95
- package/dist/index.d.ts +14 -10
- package/dist/index.js +3 -3
- package/package.json +14 -14
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2025 Vercel Inc.
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,107 +1,100 @@
|
|
|
1
1
|
# portless
|
|
2
2
|
|
|
3
|
-
Replace port numbers with stable, named .localhost URLs. For humans and agents.
|
|
3
|
+
Replace port numbers with stable, named .localhost URLs for local development. For humans and agents.
|
|
4
4
|
|
|
5
5
|
```diff
|
|
6
|
-
- "dev": "next dev"
|
|
7
|
-
+ "dev": "portless run next dev"
|
|
6
|
+
- "dev": "next dev" # http://localhost:3000
|
|
7
|
+
+ "dev": "portless run next dev" # https://myapp.localhost
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Install
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
# Install
|
|
14
13
|
npm install -g portless
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
> Install globally. Do not add as a project dependency or run via npx.
|
|
17
|
+
|
|
18
|
+
## Run your app
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Enable HTTPS (one-time setup, auto-generates certs)
|
|
22
|
+
portless proxy start --https
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
# -> http://<project>.localhost:1355
|
|
24
|
+
portless myapp next dev
|
|
25
|
+
# -> https://myapp.localhost
|
|
19
26
|
|
|
20
|
-
#
|
|
27
|
+
# Without --https, runs on port 1355
|
|
21
28
|
portless myapp next dev
|
|
22
29
|
# -> http://myapp.localhost:1355
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## Why
|
|
32
|
+
The proxy auto-starts when you run an app. A random port (4000--4999) is assigned via the `PORT` environment variable. Most frameworks (Next.js, Express, Nuxt, etc.) respect this automatically. For frameworks that ignore `PORT` (Vite, Astro, React Router, Angular), portless auto-injects `--port` and `--host` flags.
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
## Use in package.json
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- **Sharing URLs with teammates** -- "what port is that on?" becomes a Slack question
|
|
39
|
-
- **Browser history is useless** -- your history for `localhost:3000` is a jumble of unrelated projects
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"scripts": {
|
|
39
|
+
"dev": "portless run next dev"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
## Subdomains
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
Organize services with subdomains:
|
|
44
47
|
|
|
45
48
|
```bash
|
|
46
|
-
# Auto-infer name from package.json / git / directory
|
|
47
|
-
portless run next dev
|
|
48
|
-
# -> http://<project>.localhost:1355
|
|
49
|
-
|
|
50
|
-
# Explicit name
|
|
51
|
-
portless myapp next dev
|
|
52
|
-
# -> http://myapp.localhost:1355
|
|
53
|
-
|
|
54
|
-
# Subdomains
|
|
55
49
|
portless api.myapp pnpm start
|
|
56
50
|
# -> http://api.myapp.localhost:1355
|
|
57
51
|
|
|
58
52
|
portless docs.myapp next dev
|
|
59
53
|
# -> http://docs.myapp.localhost:1355
|
|
60
|
-
|
|
61
|
-
# Wildcard subdomains (no extra registration needed)
|
|
62
|
-
# Any subdomain of a registered route routes automatically:
|
|
63
|
-
# tenant1.myapp.localhost:1355 -> myapp
|
|
64
|
-
# tenant2.myapp.localhost:1355 -> myapp
|
|
65
54
|
```
|
|
66
55
|
|
|
67
|
-
|
|
56
|
+
Wildcard subdomain routing: any subdomain of a registered route routes to that app automatically (e.g. `tenant1.myapp.localhost:1355` routes to the `myapp` app without extra registration).
|
|
68
57
|
|
|
69
|
-
|
|
58
|
+
## Git Worktrees
|
|
59
|
+
|
|
60
|
+
`portless run` automatically detects git worktrees. In a linked worktree, the branch name is prepended as a subdomain so each worktree gets its own URL without any config changes:
|
|
70
61
|
|
|
71
62
|
```bash
|
|
72
|
-
# Main worktree
|
|
73
|
-
portless run next dev
|
|
74
|
-
# -> http://myapp.localhost:1355
|
|
63
|
+
# Main worktree -- no prefix
|
|
64
|
+
portless run next dev # -> http://myapp.localhost:1355
|
|
75
65
|
|
|
76
|
-
# Linked worktree on branch "fix-ui"
|
|
77
|
-
portless run next dev
|
|
78
|
-
|
|
66
|
+
# Linked worktree on branch "fix-ui"
|
|
67
|
+
portless run next dev # -> http://fix-ui.myapp.localhost:1355
|
|
68
|
+
```
|
|
79
69
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
70
|
+
Use `--name` to override the inferred base name while keeping the worktree prefix:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
portless run --name myapp next dev # -> http://fix-ui.myapp.localhost:1355
|
|
83
74
|
```
|
|
84
75
|
|
|
85
|
-
|
|
76
|
+
Put `portless run` in your `package.json` once and it works everywhere -- the main checkout uses the plain name, each worktree gets a unique subdomain. No collisions, no `--force`.
|
|
86
77
|
|
|
87
|
-
|
|
78
|
+
## Custom TLD
|
|
88
79
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
80
|
+
By default, portless uses `.localhost` which auto-resolves to `127.0.0.1` in most browsers. If you prefer a different TLD (e.g. `.test`), use `--tld`:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
sudo portless proxy start --https --tld test
|
|
84
|
+
portless myapp next dev
|
|
85
|
+
# -> https://myapp.test
|
|
95
86
|
```
|
|
96
87
|
|
|
97
|
-
The proxy auto-
|
|
88
|
+
The proxy auto-syncs `/etc/hosts` for custom TLDs when started with sudo, so `.test` domains resolve correctly.
|
|
89
|
+
|
|
90
|
+
Recommended: `.test` (IANA-reserved, no collision risk). Avoid `.local` (conflicts with mDNS/Bonjour) and `.dev` (Google-owned, forces HTTPS via HSTS).
|
|
98
91
|
|
|
99
|
-
## How
|
|
92
|
+
## How it works
|
|
100
93
|
|
|
101
94
|
```mermaid
|
|
102
95
|
flowchart TD
|
|
103
96
|
Browser["Browser\nmyapp.localhost:1355"]
|
|
104
|
-
Proxy["portless proxy
|
|
97
|
+
Proxy["portless proxy\n(port 1355)"]
|
|
105
98
|
App1[":4123\nmyapp"]
|
|
106
99
|
App2[":4567\napi"]
|
|
107
100
|
|
|
@@ -114,8 +107,6 @@ flowchart TD
|
|
|
114
107
|
2. **Run apps** -- `portless <name> <command>` assigns a free port and registers with the proxy
|
|
115
108
|
3. **Access via URL** -- `http://<name>.localhost:1355` routes through the proxy to your app
|
|
116
109
|
|
|
117
|
-
Apps are assigned a random port (4000-4999) via the `PORT` and `HOST` environment variables. Most frameworks (Next.js, Express, Nuxt, etc.) respect these automatically. For frameworks that ignore `PORT` (Vite, Astro, React Router, Angular, Expo, React Native), portless auto-injects the correct `--port` and `--host` flags.
|
|
118
|
-
|
|
119
110
|
## HTTP/2 + HTTPS
|
|
120
111
|
|
|
121
112
|
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.
|
|
@@ -138,12 +129,12 @@ portless proxy start --cert ./cert.pem --key ./key.pem
|
|
|
138
129
|
sudo portless trust
|
|
139
130
|
```
|
|
140
131
|
|
|
141
|
-
On Linux, `portless trust` supports Debian/Ubuntu, Arch, Fedora/RHEL/CentOS, and openSUSE (via `update-ca-certificates` or `update-ca-trust`).
|
|
132
|
+
On Linux, `portless trust` supports Debian/Ubuntu, Arch, Fedora/RHEL/CentOS, and openSUSE (via `update-ca-certificates` or `update-ca-trust`). On Windows, it uses `certutil` to add the CA to the system trust store.
|
|
142
133
|
|
|
143
134
|
## Commands
|
|
144
135
|
|
|
145
136
|
```bash
|
|
146
|
-
portless run <cmd> [args...]
|
|
137
|
+
portless run [--name <name>] <cmd> [args...] # Infer name (or override with --name), run through proxy
|
|
147
138
|
portless <name> <cmd> [args...] # Run app at http://<name>.localhost:1355
|
|
148
139
|
portless alias <name> <port> # Register a static route (e.g. for Docker)
|
|
149
140
|
portless alias <name> <port> --force # Overwrite an existing route
|
|
@@ -155,7 +146,6 @@ portless hosts clean # Remove portless entries from /etc/hosts
|
|
|
155
146
|
|
|
156
147
|
# Disable portless (run command directly)
|
|
157
148
|
PORTLESS=0 pnpm dev # Bypasses proxy, uses default port
|
|
158
|
-
# Also accepts PORTLESS=skip
|
|
159
149
|
|
|
160
150
|
# Proxy control
|
|
161
151
|
portless proxy start # Start the proxy (port 1355, daemon)
|
|
@@ -163,64 +153,42 @@ portless proxy start --https # Start with HTTP/2 + TLS
|
|
|
163
153
|
portless proxy start -p 80 # Start on port 80 (requires sudo)
|
|
164
154
|
portless proxy start --foreground # Start in foreground (for debugging)
|
|
165
155
|
portless proxy stop # Stop the proxy
|
|
166
|
-
|
|
167
|
-
# Options
|
|
168
|
-
-p, --port <number> # Port for the proxy (default: 1355)
|
|
169
|
-
# Ports < 1024 require sudo
|
|
170
|
-
--https # Enable HTTP/2 + TLS with auto-generated certs
|
|
171
|
-
--cert <path> # Use a custom TLS certificate (implies --https)
|
|
172
|
-
--key <path> # Use a custom TLS private key (implies --https)
|
|
173
|
-
--no-tls # Disable HTTPS (overrides PORTLESS_HTTPS)
|
|
174
|
-
--foreground # Run proxy in foreground instead of daemon
|
|
175
|
-
--app-port <number> # Use a fixed port for the app (skip auto-assignment)
|
|
176
|
-
--force # Override a route registered by another process
|
|
177
|
-
--name <name> # Use <name> as the app name (bypasses subcommand dispatch)
|
|
178
|
-
-- # Stop flag parsing; everything after is passed to the child
|
|
179
|
-
|
|
180
|
-
# Injected into child processes
|
|
181
|
-
PORT # Ephemeral port the child should listen on
|
|
182
|
-
HOST # Always 127.0.0.1
|
|
183
|
-
PORTLESS_URL # Public URL (e.g. http://myapp.localhost:1355)
|
|
184
|
-
|
|
185
|
-
# Configuration
|
|
186
|
-
PORTLESS_PORT=<number> # Override the default proxy port
|
|
187
|
-
PORTLESS_APP_PORT=<number> # Use a fixed port for the app (same as --app-port)
|
|
188
|
-
PORTLESS_HTTPS=1|true # Always enable HTTPS
|
|
189
|
-
PORTLESS_SYNC_HOSTS=1 # Auto-sync /etc/hosts when routes change
|
|
190
|
-
PORTLESS_STATE_DIR=<path> # Override the state directory
|
|
191
|
-
|
|
192
|
-
# Info
|
|
193
|
-
portless --help # Show help
|
|
194
|
-
portless run --help # Show help for a specific subcommand
|
|
195
|
-
portless --version # Show version
|
|
196
156
|
```
|
|
197
157
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
## State Directory
|
|
201
|
-
|
|
202
|
-
Portless stores its state (routes, PID file, port file) in a directory that depends on the proxy port:
|
|
203
|
-
|
|
204
|
-
- **Port < 1024** (sudo required): `/tmp/portless` -- shared between root and user processes
|
|
205
|
-
- **Port >= 1024** (no sudo): `~/.portless` -- user-scoped, no root involvement
|
|
158
|
+
### Options
|
|
206
159
|
|
|
207
|
-
|
|
160
|
+
```
|
|
161
|
+
-p, --port <number> Port for the proxy (default: 1355)
|
|
162
|
+
--https Enable HTTP/2 + TLS with auto-generated certs
|
|
163
|
+
--cert <path> Use a custom TLS certificate (implies --https)
|
|
164
|
+
--key <path> Use a custom TLS private key (implies --https)
|
|
165
|
+
--no-tls Disable HTTPS (overrides PORTLESS_HTTPS)
|
|
166
|
+
--foreground Run proxy in foreground instead of daemon
|
|
167
|
+
--tld <tld> Use a custom TLD instead of .localhost (e.g. test)
|
|
168
|
+
--app-port <number> Use a fixed port for the app (skip auto-assignment)
|
|
169
|
+
--force Override a route registered by another process
|
|
170
|
+
--name <name> Use <name> as the app name
|
|
171
|
+
```
|
|
208
172
|
|
|
209
|
-
|
|
173
|
+
### Environment variables
|
|
210
174
|
|
|
211
|
-
|
|
175
|
+
```
|
|
176
|
+
# Configuration
|
|
177
|
+
PORTLESS_PORT=<number> Override the default proxy port
|
|
178
|
+
PORTLESS_APP_PORT=<number> Use a fixed port for the app (same as --app-port)
|
|
179
|
+
PORTLESS_HTTPS=1 Always enable HTTPS
|
|
180
|
+
PORTLESS_TLD=<tld> Use a custom TLD (e.g. test; default: localhost)
|
|
181
|
+
PORTLESS_SYNC_HOSTS=1 Auto-sync /etc/hosts (auto-enabled for custom TLDs)
|
|
182
|
+
PORTLESS_STATE_DIR=<path> Override the state directory
|
|
212
183
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
pnpm test:coverage # Run tests with coverage
|
|
218
|
-
pnpm test:watch # Run tests in watch mode
|
|
219
|
-
pnpm lint # Lint all packages
|
|
220
|
-
pnpm typecheck # Type-check all packages
|
|
221
|
-
pnpm format # Format all files with Prettier
|
|
184
|
+
# Injected into child processes
|
|
185
|
+
PORT Ephemeral port the child should listen on
|
|
186
|
+
HOST Always 127.0.0.1
|
|
187
|
+
PORTLESS_URL Public URL (e.g. https://myapp.localhost)
|
|
222
188
|
```
|
|
223
189
|
|
|
190
|
+
> **Reserved names:** `run`, `get`, `alias`, `hosts`, `list`, `trust`, and `proxy` are subcommands and cannot be used as app names directly. Use `portless run <cmd>` to infer the name from your project, or `portless --name <name> <cmd>` to force any name including reserved ones.
|
|
191
|
+
|
|
224
192
|
## Safari / DNS
|
|
225
193
|
|
|
226
194
|
`.localhost` subdomains auto-resolve to `127.0.0.1` in Chrome, Firefox, and Edge. Safari relies on the system DNS resolver, which may not handle `.localhost` subdomains on all configurations.
|
|
@@ -228,23 +196,15 @@ pnpm format # Format all files with Prettier
|
|
|
228
196
|
If Safari can't find your `.localhost` URL:
|
|
229
197
|
|
|
230
198
|
```bash
|
|
231
|
-
# Add current routes to /etc/hosts
|
|
232
|
-
sudo portless hosts
|
|
233
|
-
|
|
234
|
-
# Clean up later
|
|
235
|
-
sudo portless hosts clean
|
|
199
|
+
sudo portless hosts sync # Add current routes to /etc/hosts
|
|
200
|
+
sudo portless hosts clean # Clean up later
|
|
236
201
|
```
|
|
237
202
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
export PORTLESS_SYNC_HOSTS=1
|
|
242
|
-
sudo portless proxy start
|
|
243
|
-
```
|
|
203
|
+
Auto-syncs `/etc/hosts` for custom TLDs (e.g. `--tld test`). For `.localhost`, set `PORTLESS_SYNC_HOSTS=1` to enable. Disable with `PORTLESS_SYNC_HOSTS=0`.
|
|
244
204
|
|
|
245
205
|
## Proxying Between Portless Apps
|
|
246
206
|
|
|
247
|
-
If your frontend dev server (e.g. Vite, webpack) proxies API requests to another portless app, make sure the proxy rewrites the `Host` header. Without this,
|
|
207
|
+
If your frontend dev server (e.g. Vite, webpack) proxies API requests to another portless app, make sure the proxy rewrites the `Host` header. Without this, portless routes the request back to the frontend in an infinite loop.
|
|
248
208
|
|
|
249
209
|
**Vite** (`vite.config.ts`):
|
|
250
210
|
|
|
@@ -253,7 +213,7 @@ server: {
|
|
|
253
213
|
proxy: {
|
|
254
214
|
"/api": {
|
|
255
215
|
target: "http://api.myapp.localhost:1355",
|
|
256
|
-
changeOrigin: true,
|
|
216
|
+
changeOrigin: true,
|
|
257
217
|
ws: true,
|
|
258
218
|
},
|
|
259
219
|
},
|
|
@@ -267,14 +227,28 @@ devServer: {
|
|
|
267
227
|
proxy: [{
|
|
268
228
|
context: ["/api"],
|
|
269
229
|
target: "http://api.myapp.localhost:1355",
|
|
270
|
-
changeOrigin: true,
|
|
230
|
+
changeOrigin: true,
|
|
271
231
|
}],
|
|
272
232
|
}
|
|
273
233
|
```
|
|
274
234
|
|
|
275
235
|
Portless detects this misconfiguration and responds with `508 Loop Detected` along with a message pointing to this fix.
|
|
276
236
|
|
|
237
|
+
## Development
|
|
238
|
+
|
|
239
|
+
This repo is a pnpm workspace monorepo using [Turborepo](https://turbo.build). The publishable package lives in `packages/portless/`.
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
pnpm install # Install all dependencies
|
|
243
|
+
pnpm build # Build all packages
|
|
244
|
+
pnpm test # Run tests
|
|
245
|
+
pnpm test:coverage # Run tests with coverage
|
|
246
|
+
pnpm lint # Lint all packages
|
|
247
|
+
pnpm typecheck # Type-check all packages
|
|
248
|
+
pnpm format # Format all files with Prettier
|
|
249
|
+
```
|
|
250
|
+
|
|
277
251
|
## Requirements
|
|
278
252
|
|
|
279
253
|
- Node.js 20+
|
|
280
|
-
- macOS or
|
|
254
|
+
- macOS, Linux, or Windows
|