slash-port 0.2.1 → 0.4.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/README.md CHANGED
@@ -1,6 +1,16 @@
1
+ <p align="center">
2
+ <a href="https://github.com/Slash-ui">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="docs/assets/logo-slashui-dark.svg" />
5
+ <img src="docs/assets/logo-slashui-light.svg" alt="Slash UI" width="159" height="65" />
6
+ </picture>
7
+ </a>
8
+ </p>
9
+
1
10
  # slash-port
2
11
 
3
- <!-- release:badge -->[![github](https://img.shields.io/badge/github-v0.2.1-0f8b7d?logo=github&logoColor=white)](https://github.com/Slash-ui/slash-port/releases/tag/v0.2.1)<!-- /release:badge -->
12
+ <!-- release:badge -->
13
+ [![github](https://img.shields.io/badge/github-v0.4.0-0f8b7d?logo=github&logoColor=white)](https://github.com/Slash-ui/slash-port/releases/tag/v0.4.0)<!-- /release:badge -->
4
14
  [![npm](https://img.shields.io/npm/v/slash-port?logo=npm&logoColor=white&color=0f8b7d)](https://www.npmjs.com/package/slash-port)
5
15
  [![downloads](https://img.shields.io/npm/dm/slash-port?color=0f8b7d)](https://www.npmjs.com/package/slash-port)
6
16
  [![CI](https://github.com/Slash-ui/slash-port/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Slash-ui/slash-port/actions/workflows/ci.yml)
@@ -19,15 +29,60 @@ a good idea. `slash-port` answers all three, then kills the process for you
19
29
  after a confirmation that names it.
20
30
 
21
31
  ```
22
- slash-port 6/6 tcp
23
- PORT PID USER PROCESS DESCRIPTION
24
- 3000/tcp 41822 amin node Next.js (shop)
25
- 5173/tcp 41905 amin node Vite dev server (admin)
26
- 5432/tcp 612 postgres postgres PostgreSQL
27
- 6379/tcp 788 redis redis-server Redis
28
- 8080/tcp 39044 amin docker-proxy Docker published port
29
- 22/tcp 1 root sshd OpenSSH server [protected]
30
- ↑↓/jk move · PgUp/PgDn/g/G jump · / filter · x kill · r rescan · u udp · q quit
32
+ slash-port 8/8 tcp · beginner
33
+ PORT WHAT IT IS OPEN AT CLOSE IT?
34
+ 22/tcp OpenSSH server [protected] - No
35
+ 3000/tcp Next.js (shop) http://localhost:3000 Yes
36
+ 5173/tcp Vite dev server (admin) http://localhost:5173 Yes
37
+ 5432/tcp Docker Desktop - Probably
38
+ 6379/tcp Redis - Probably
39
+ 8025/tcp Docker Desktop http://localhost:8025 Probably
40
+ 49470/tcp Visual Studio Code (Node.js) - Probably
41
+ 51061/tcp macOS Handoff - Better not
42
+ ╭──────────────────────────────────────────────────────────────────────────────╮
43
+ │ Port 3000 · Next.js (shop) - a web server │
44
+ │ Point a browser at it - that is what it is there for. │
45
+ │ Project shop │
46
+ │ Open http://localhost:3000 │
47
+ │ Started by you (slashui) · node · pid 41822 │
48
+ │ Close it Yes - yours, and as easy to start again as it was to start │
49
+ │ Afterwards Start it again with your dev command, usually `npm run dev`. │
50
+ ╰──────────────────────────────────────────────────────────────────────────────╯
51
+ ↑↓ move · / find · x close it · r refresh · u udp · d details · m advanced · q …
52
+ ```
53
+
54
+ Every row says something the process name does not. The process behind
55
+ `Visual Studio Code` is called `Code Helper`, and the one behind `macOS
56
+ Handoff` is called `rapportd`. Neither name would have told you anything, which
57
+ is the point: when nothing at all can be worked out, the column says `-` rather
58
+ than repeating the process name back at you.
59
+
60
+ Press `m` for advanced mode, which trades the explanations for the facts that
61
+ tell two identical-looking dev servers apart:
62
+
63
+ ```
64
+ slash-port 8/8 tcp · advanced
65
+ PORT PID USER PROCESS ADDRESS DESCRIPTION
66
+ 22/tcp 947 root sshd * OpenSSH server [protected]
67
+ 3000/tcp 41822 slashui node * Next.js (shop)
68
+ 5173/tcp 41905 slashui node * Vite dev server (admin)
69
+ 5432/tcp 39044 slashui com.docker.backend * Docker Desktop
70
+ 6379/tcp 788 slashui redis-server 127.0.0.1 Redis
71
+ 8025/tcp 39044 slashui com.docker.backend * Docker Desktop
72
+ 49470/tcp 1737 slashui Code Helper 127.0.0.1 Visual Studio Code (Node.js)
73
+ 51061/tcp 694 slashui rapportd * macOS Handoff
74
+ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
75
+ │ Process node · pid 41822 · parent 1204 zsh │
76
+ │ User slashui │
77
+ │ Listening * · TCP · IPv4 │
78
+ │ Clients 3 connections open │
79
+ │ Running 2h 11m (since 14:02) │
80
+ │ Memory 431 MB · 0.4% CPU │
81
+ │ Directory /Users/slashui/code/shop │
82
+ │ Command node /Users/slashui/code/shop/node_modules/.bin/next dev │
83
+ │ Kill Yes - yours, and as easy to start again as it was to start. Start it again with your … │
84
+ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
85
+ ↑↓/jk move · PgUp/PgDn/g/G jump · / filter · x kill · r rescan · u udp · d detail · m beginner · q …
31
86
  ```
32
87
 
33
88
  ## Install
@@ -46,9 +101,8 @@ Requires Node 22 or newer. Works on Linux, macOS, and Windows.
46
101
 
47
102
  ### Updating
48
103
 
49
- The current release is
50
- <!-- release:version -->0.2.1<!-- /release:version -->. To see what you have,
51
- and what is published:
104
+ The current release is <!-- release:version -->0.4.0<!-- /release:version -->. To
105
+ see what you have, and what is published:
52
106
 
53
107
  ```sh
54
108
  slash-port --version # the one you are running
@@ -90,15 +144,90 @@ reading before you take it.
90
144
  ## Use
91
145
 
92
146
  ```sh
93
- slash-port # the interactive list
147
+ slash-port # the interactive list, in beginner mode
148
+ slash-port --advanced # the same list, with the full detail
94
149
  slash-port 3000 # open on port 3000
95
150
  slash-port 3xxx # every port from 3000 to 3999
96
151
  slash-port 3000:3005 # every port in that range
97
152
  slash-port --plain # a plain table, for a pipe or a script
98
153
  slash-port --json # the same data as JSON
99
154
  slash-port --udp # include UDP as well as TCP
155
+ slash-port --docker # name the container behind a published port
100
156
  ```
101
157
 
158
+ ### Beginner and advanced
159
+
160
+ There are two modes, and **beginner is the default**. The person who does not
161
+ know what took port 3000 is the person who went looking for a tool that would
162
+ tell them; anyone who already knows can say `--advanced` once, or set
163
+ `SLASH_PORT_MODE=advanced` and never say it again. `m` switches between them
164
+ at any time, and `d` hides the panel in either.
165
+
166
+ | | Beginner | Advanced |
167
+ | --- | --- | --- |
168
+ | Columns | Port, what it is, where to open it, whether to close it | Port, pid, user, process, address, description |
169
+ | Narrow terminals | Keeps the verdict down to forty-two columns; the URL column stands down first, and stands down entirely when no row has one | Drops address, user, process, pid, in that order |
170
+ | Panel | What kind of thing it is, which project, who started it, whether closing it is a good idea, and how to start it again | Parent process, open connections, uptime, memory, working directory, full command line, and how the description was arrived at |
171
+ | Confirmation | Says what closing it costs and how to undo it | Names the signal |
172
+ | Cost | One scan | One scan, plus a lookup for the row under the cursor |
173
+
174
+ Both modes on a working machine, where the list is forty-two ports long
175
+ rather than the tidy eight above:
176
+
177
+ ![Beginner mode on a real machine: mailpit and adminer in Docker, five
178
+ http.server processes on 8001 to 8005, Ollama, Figma, Visual Studio Code and
179
+ macOS Handoff, each with where to open it and whether closing it is a good
180
+ idea, and a panel explaining that port 8001 is a web server and safe to
181
+ close](docs/assets/screenshot-beginner.png)
182
+
183
+ ![The same machine in advanced mode: pid, user, process and address for every
184
+ row, and a panel with the parent process, open connections, uptime, memory,
185
+ working directory and the full command
186
+ line](docs/assets/screenshot-advanced.png)
187
+
188
+ Advanced mode's extra facts are fetched for the selected row only. A machine
189
+ with four hundred listening sockets would otherwise pay four hundred times over
190
+ for facts you are reading one row at a time.
191
+
192
+ ### Docker
193
+
194
+ A published container port shows as `Docker Desktop`, which is true and no help
195
+ at all - and the beginner panel says so rather than leaving you to wonder where
196
+ the name went:
197
+
198
+ ```
199
+ ╭──────────────────────────────────────────────────────────────────────────────╮
200
+ │ Port 5432 · Docker Desktop - a container port │
201
+ │ Publishing a port on behalf of a container. │
202
+ │ Container not looked up - re-run with --docker to name it │
203
+ │ Started by you (slashui) · com.docker.backend · pid 39044 │
204
+ │ Close it Probably - yours, but something may be relying on it │
205
+ │ Afterwards Stopping the container that owns the port is the change you prob… │
206
+ ╰──────────────────────────────────────────────────────────────────────────────╯
207
+ ```
208
+
209
+ `--docker` asks the local engine which container is behind the port. The image
210
+ is read the same way a command line is, so `postgres:16` reports PostgreSQL and
211
+ is treated with the care a database deserves, and the compose project becomes
212
+ the hint - which is how two Supabase stacks on 5432 and 54322 stop being
213
+ interchangeable:
214
+
215
+ ```
216
+ ╭──────────────────────────────────────────────────────────────────────────────╮
217
+ │ Port 5432 · PostgreSQL in Docker (shop) - a database │
218
+ │ The container shop-db, from the shop compose project, running postgres:16-a… │
219
+ │ Container shop │
220
+ │ Started by you (slashui) · com.docker.backend · pid 39044 │
221
+ │ Close it Probably - stop the container instead: `docker stop shop-db` │
222
+ │ Afterwards Bring it back with `docker compose up -d db`. │
223
+ ╰──────────────────────────────────────────────────────────────────────────────╯
224
+ ```
225
+
226
+ It stays off until you ask for it. Reading two local tables and stopping is the
227
+ property this tool is built around, and a nicer default is not worth trading it
228
+ for. `SLASH_PORT_DOCKER=1` turns it on for good if you would rather not type
229
+ it, and `--no-docker` overrules that for one run.
230
+
102
231
  ### Naming ports
103
232
 
104
233
  `--port` and the interactive filter take the same three forms:
@@ -140,6 +269,8 @@ There is no flag combination that kills something without naming it first.
140
269
  | `x` or `Enter` | Kill the selected port |
141
270
  | `r` | Rescan |
142
271
  | `u` | Show UDP as well as TCP |
272
+ | `m` | Switch between beginner and advanced |
273
+ | `d` | Show or hide the detail panel |
143
274
  | `q` | Quit |
144
275
 
145
276
  In the confirmation dialog: `y` sends SIGTERM, `f` forces with SIGKILL, `n`
@@ -150,7 +281,11 @@ cancels. The kill key is deliberately not next to a navigation key.
150
281
  | Option | Does |
151
282
  | --- | --- |
152
283
  | `-p`, `--port <ports>` | Only these ports: `3000`, `3xxx`, or `3000:3005` |
284
+ | `--beginner` | Explain each port in plain language. The default |
285
+ | `--advanced` | Show the full detail instead of the explanations |
286
+ | `--mode <name>` | `beginner` or `advanced`. `SLASH_PORT_MODE` sets the default |
153
287
  | `-u`, `--udp` | Include UDP sockets |
288
+ | `--docker` | Ask the local Docker socket which container holds a port. Off by default; `SLASH_PORT_DOCKER=1` sets the default |
154
289
  | `--json` | Print JSON and exit |
155
290
  | `--plain` | Print a plain table and exit |
156
291
  | `--kill` | Kill the process on `--port`. Requires `--yes` |
@@ -162,6 +297,19 @@ cancels. The kill key is deliberately not next to a navigation key.
162
297
  | `-h`, `--help` | Show help |
163
298
  | `-v`, `--version` | Show the version |
164
299
 
300
+ ### Output for scripts
301
+
302
+ `--json` is the stable machine surface. Fields are added over time and never
303
+ repurposed, so a `jq` expression written against an old version keeps working.
304
+ `description` is `null` rather than a copy of `process` when nothing could be
305
+ identified, which is the one thing worth knowing before parsing it: absence is
306
+ reported as absence.
307
+
308
+ `--plain` keeps the same six columns in both modes and always will, so anything
309
+ already splitting that output keeps working. A mode only ever appends a column
310
+ on the end - what closing it would mean in beginner mode, the full command line
311
+ in advanced.
312
+
165
313
  ### Exit codes
166
314
 
167
315
  The same codes across every `slash-*` tool, so a script that wraps one can wrap
@@ -204,11 +352,28 @@ are fixed rather than configurable:
204
352
  init process, `sshd` - killing it locks you out of a remote machine - macOS
205
353
  and Windows session processes, `slash-port` itself, and the shell that
206
354
  launched it.
355
+ - **Whether closing it is a good idea is settled before you decide.** Every row
356
+ carries a verdict - `Yes`, `Probably`, `Better not`, `No`, `Needs sudo` -
357
+ worked out from what it is, who owns it, and whether a guardrail already
358
+ refuses it. The verdict is a word in a column, never a colour alone.
359
+ - **The confirmation is never the thing that gets truncated.** On a terminal
360
+ too short to show it and the list behind it, the list gives way; a question
361
+ you cannot read is a question you cannot answer.
207
362
  - **SIGTERM before SIGKILL.** A process that ignores SIGTERM is reported as
208
363
  having survived. Escalating is a second, deliberate action, never automatic.
209
364
  - **A process that has already exited is never signalled**, because by then its
210
365
  pid may belong to something else.
211
366
 
367
+ The confirmation for a row that is safe to close names the process, says what
368
+ closing it costs, and keeps the polite close and the forced one on separate
369
+ keys:
370
+
371
+ ![The confirmation over the list: Close whatever is using port 8002, the
372
+ process named as Python http.server, pid 11575, user slashui, the verdict that
373
+ it is yours and as easy to start again as it was to start, and the keys y to
374
+ close it politely, f to force it, n to leave it
375
+ alone](docs/assets/screenshot-close.png)
376
+
212
377
  On Windows there is no signal delivery: SIGTERM becomes `TerminateProcess`,
213
378
  which a process cannot catch or ignore, so nothing there gets the chance to
214
379
  shut down cleanly. The confirmation still applies - but "terminate" and "force"
@@ -216,9 +381,17 @@ do the same thing.
216
381
 
217
382
  ## Privacy
218
383
 
219
- `slash-port` makes no network connections at any point. It reads the local
220
- socket table and the local process table, and that is all it does. There is no
221
- telemetry, no update check, and no configuration file.
384
+ `slash-port` makes no network connections at any point. By default it reads
385
+ the local socket table and the local process table, and asks nothing else on
386
+ the machine anything either. There is no telemetry, no update check, and no
387
+ configuration file.
388
+
389
+ `--docker` is the single exception, and it is off until you ask for it. It
390
+ reads the local Docker socket - a file on this machine, the same as
391
+ `/proc/net/tcp` is - to name the container behind a published port. A
392
+ `DOCKER_HOST` pointing at another machine over TCP is ignored rather than
393
+ connected to. `SLASH_PORT_DOCKER=1` turns it on for good if you would rather
394
+ not type it; `--no-docker` still overrules that for one run.
222
395
 
223
396
  ## Terminal behaviour
224
397
 
@@ -233,19 +406,50 @@ telemetry, no update check, and no configuration file.
233
406
  - The list is windowed to the visible rows, so a machine with four hundred
234
407
  listening sockets renders a screenful, not four hundred lines.
235
408
  - Columns are dropped in order of how little they carry as the window narrows,
236
- and values that are cut are marked with an ellipsis.
409
+ and values that are cut are marked with an ellipsis. Beginner mode keeps all
410
+ four of its columns down to eighty, because the fourth is the answer.
411
+ - A column that has nothing to show stands down rather than printing a column
412
+ of dashes: `OPEN AT` appears when the rows on screen have URLs.
237
413
 
238
414
  ## How it identifies a process
239
415
 
240
- Three sources, in priority order:
416
+ The description column exists to say something the process column did not. So
417
+ the first rule is that it never repeats the process name: when nothing could be
418
+ worked out, it says `-`, because "slash-port has no idea" is a fact and
419
+ `figma_agent` beside `figma_agent` is a column doing nothing.
420
+
421
+ What it consults, in priority order:
241
422
 
242
423
  1. **The command line.** Specific frameworks are matched before the runtimes
243
424
  that host them, so `node …/vite` reports Vite rather than Node.js.
244
- 2. **The project.** The directory above `node_modules` in the command line, so
245
- two Vite servers on 5173 and 5174 can be told apart.
246
- 3. **A well-known port registry**, used only when the process itself could not
247
- be identified - mostly other users' processes. Entries that would add
248
- nothing are suppressed: "dev server" on port 3000 is not information.
425
+ 2. **The container**, if you passed `--docker`. The local engine is asked which
426
+ container publishes the port, and the image is then read like a command
427
+ line, so `postgres:16` reports "PostgreSQL in Docker" and is treated with
428
+ the care a database deserves. The compose project - or the container name
429
+ when there is no project - becomes the hint, which is how `5432` and `54322`
430
+ stop being interchangeable. Without the flag a published port reports
431
+ `Docker Desktop`, and beginner mode says so rather than leaving you to
432
+ wonder why the name is missing.
433
+ 3. **The application.** The bundle or install directory the binary sits in,
434
+ so `Code Helper` reports Visual Studio Code and `figma_agent` reports Figma.
435
+ The outermost bundle wins, and a vendor directory beats the bundle inside it.
436
+ 4. **The project.** The directory above `node_modules` in the command line, so
437
+ two Vite servers on 5173 and 5174 can be told apart. A directory that only
438
+ names a convention - `lib`, `src`, `bin` - is passed over for the script
439
+ itself, which is why `…/google-cloud-sdk/lib/gcloud.py` reads as `gcloud`.
440
+ 5. **A well-known port registry**, for processes that could not be identified
441
+ at all - mostly other users'. Generic entries are demoted rather than
442
+ suppressed: "dev server" loses to anything specific, and beats saying
443
+ nothing.
444
+ 6. **The shape of the path.** A binary under `/usr/libexec` is a system service
445
+ whoever wrote it, which is worth more than its own name repeated back.
446
+
447
+ Beginner mode adds one more question on top of all that: whether closing it is
448
+ a good idea. That answer folds together what kind of thing it is, whether you
449
+ own it, and whether a guardrail already refuses it - and the last two win,
450
+ because they are facts about this machine rather than guesses about software. A
451
+ Postgres you do not own is `Needs sudo` whatever anyone thinks of closing
452
+ databases.
249
453
 
250
454
  Per platform:
251
455
 
@@ -258,14 +462,22 @@ Per platform:
258
462
  - **Windows** uses `netstat -ano` and `tasklist`, which exist on every edition
259
463
  and avoid PowerShell's startup cost.
260
464
 
465
+ Advanced mode's per-row lookups follow the same rule of asking the cheapest
466
+ thing that can answer: `/proc` on Linux with no subprocess at all, `ps` and
467
+ `lsof` on macOS, and on Windows only what `tasklist` and `netstat` already
468
+ know. Parents, working directories, and start times need WMI or PowerShell
469
+ there, which cost about a second each, so those lines are left out rather than
470
+ paid for. A platform that cannot answer omits the line; it never guesses.
471
+
261
472
  ## Not built yet
262
473
 
263
474
  Deliberate omissions, listed so you know they are choices rather than
264
475
  oversights:
265
476
 
266
- - **Docker awareness.** A published port shows `docker-proxy` rather than the
267
- container behind it. Resolving that means talking to the Docker socket, which
268
- is a real dependency and belongs behind a flag.
477
+ - **Docker awareness by default.** `--docker` names the container behind a
478
+ published port, and it stays opt-in. Reading two local tables and stopping is
479
+ the property this tool is built around, and it is not worth trading for a
480
+ nicer default.
269
481
  - **Process trees.** Killing a dev server sometimes leaves children behind. A
270
482
  `--tree` option would signal the whole group.
271
483
  - **Watch mode.** The list rescans on `r`, not on a timer.
package/dist/cli.js CHANGED
@@ -3,6 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { readFileSync } from 'node:fs';
4
4
  import { plainTable, toJson } from './format.js';
5
5
  import { killEntry } from './kill.js';
6
+ import { isMode, resolveDocker, resolveMode } from './mode.js';
6
7
  import { describePortSelector, looksLikePort, matchesPort, parsePortSelector } from './ports.js';
7
8
  import { scan } from './scan/index.js';
8
9
  import { ScanError } from './types.js';
@@ -39,7 +40,9 @@ class UsageError extends Error {
39
40
  function parseArgs(argv) {
40
41
  const options = {
41
42
  port: null,
43
+ mode: null,
42
44
  udp: false,
45
+ docker: null,
43
46
  json: false,
44
47
  plain: false,
45
48
  kill: false,
@@ -73,10 +76,29 @@ function parseArgs(argv) {
73
76
  case '--port':
74
77
  options.port = selector(value(argument, argv[++index]));
75
78
  break;
79
+ case '--beginner':
80
+ options.mode = 'beginner';
81
+ break;
82
+ case '--advanced':
83
+ options.mode = 'advanced';
84
+ break;
85
+ case '--mode': {
86
+ const raw = value(argument, argv[++index]).toLowerCase();
87
+ if (!isMode(raw))
88
+ throw new UsageError(`${raw} is not a mode. Use beginner or advanced.`);
89
+ options.mode = raw;
90
+ break;
91
+ }
76
92
  case '-u':
77
93
  case '--udp':
78
94
  options.udp = true;
79
95
  break;
96
+ case '--docker':
97
+ options.docker = true;
98
+ break;
99
+ case '--no-docker':
100
+ options.docker = false;
101
+ break;
80
102
  case '--json':
81
103
  options.json = true;
82
104
  break;
@@ -159,7 +181,11 @@ Ports
159
181
 
160
182
  Options
161
183
  -p, --port <ports> Only these ports, in any of the forms above
184
+ --beginner Explain each port in plain language (the default)
185
+ --advanced Show the full detail instead of the explanations
186
+ --mode <name> beginner or advanced. SLASH_PORT_MODE sets the default
162
187
  -u, --udp Include UDP sockets as well as TCP
188
+ --docker Ask the local Docker socket which container holds a port
163
189
  --json Print JSON to stdout and exit
164
190
  --plain Print a plain table and exit
165
191
  --kill Kill the process on --port. Requires --yes
@@ -175,6 +201,13 @@ Keys
175
201
  up/down or j/k move / filter x or Enter kill
176
202
  PgUp/PgDn page r rescan u toggle UDP
177
203
  g / G first / last q quit y/f/n confirm dialog
204
+ m switch mode d show or hide the detail panel
205
+
206
+ Modes
207
+ Beginner mode is the default. It says what each port is in plain language,
208
+ where to open it, and whether closing it is a good idea. Advanced mode shows
209
+ pids, users, bind addresses, command lines, working directories, uptime, and
210
+ how many connections are open. Press m to switch, or set SLASH_PORT_MODE.
178
211
 
179
212
  Exit codes
180
213
  0 success
@@ -184,8 +217,12 @@ Exit codes
184
217
  4 the operation was attempted and failed
185
218
 
186
219
  slash-port never kills without confirmation; never kills init, sshd, your
187
- session, or the shell that launched it; sends SIGTERM before SIGKILL; and
188
- never touches the network.`;
220
+ session, or the shell that launched it; and sends SIGTERM before SIGKILL.
221
+
222
+ It makes no network connections, and asks nothing else on the machine anything
223
+ either. --docker is the single exception: it reads the local Docker socket - a
224
+ file on this machine - for the name of the container behind a published port.
225
+ SLASH_PORT_DOCKER=1 turns that on for good.`;
189
226
  function readVersion() {
190
227
  try {
191
228
  const manifest = readFileSync(new URL('../package.json', import.meta.url), 'utf8');
@@ -247,6 +284,8 @@ async function main(argv) {
247
284
  process.stderr.write('\nRun slash-port --help for usage.\n');
248
285
  return code;
249
286
  }
287
+ const mode = resolveMode(options.mode);
288
+ const docker = resolveDocker(options.docker);
250
289
  if (options.help) {
251
290
  process.stdout.write(`${HELP}\n`);
252
291
  return EXIT_OK;
@@ -261,7 +300,7 @@ async function main(argv) {
261
300
  process.env['NO_COLOR'] = '1';
262
301
  let entries;
263
302
  try {
264
- entries = await scan({ udp: options.udp });
303
+ entries = await scan({ udp: options.udp, docker });
265
304
  }
266
305
  catch (error) {
267
306
  if (error instanceof ScanError) {
@@ -283,14 +322,14 @@ async function main(argv) {
283
322
  process.stdout.write(`${JSON.stringify(toJson(selected), null, 2)}\n`);
284
323
  }
285
324
  else {
286
- process.stdout.write(`${plainTable(selected)}\n`);
325
+ process.stdout.write(`${plainTable(selected, mode)}\n`);
287
326
  }
288
327
  // Asking about a port is a question with a yes-or-no answer, so an empty
289
328
  // result means not found. Asking for the whole list is not a question.
290
329
  return options.port !== null && selected.length === 0 ? EXIT_NOT_FOUND : EXIT_OK;
291
330
  }
292
331
  const [{ render }, { App }] = await Promise.all([import('ink'), import('./ui/App.js')]);
293
- const instance = render(_jsx(App, { initialEntries: entries, initialFilter: options.port === null ? '' : options.port.text, udp: options.udp }));
332
+ const instance = render(_jsx(App, { initialEntries: entries, initialFilter: options.port === null ? '' : options.port.text, udp: options.udp, docker: docker, mode: mode }));
294
333
  await instance.waitUntilExit();
295
334
  return EXIT_OK;
296
335
  }