slash-port 0.2.1 → 0.3.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,6 @@
1
1
  # slash-port
2
2
 
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 -->
3
+ <!-- release:badge -->[![github](https://img.shields.io/badge/github-v0.3.0-0f8b7d?logo=github&logoColor=white)](https://github.com/Slash-ui/slash-port/releases/tag/v0.3.0)<!-- /release:badge -->
4
4
  [![npm](https://img.shields.io/npm/v/slash-port?logo=npm&logoColor=white&color=0f8b7d)](https://www.npmjs.com/package/slash-port)
5
5
  [![downloads](https://img.shields.io/npm/dm/slash-port?color=0f8b7d)](https://www.npmjs.com/package/slash-port)
6
6
  [![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 +19,60 @@ a good idea. `slash-port` answers all three, then kills the process for you
19
19
  after a confirmation that names it.
20
20
 
21
21
  ```
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
22
+ slash-port 8/8 tcp · beginner
23
+ PORT WHAT IT IS OPEN AT CLOSE IT?
24
+ 22/tcp OpenSSH server [protected] - No
25
+ 3000/tcp Next.js (shop) http://localhost:3000 Yes
26
+ 5173/tcp Vite dev server (admin) http://localhost:5173 Yes
27
+ 5432/tcp Docker Desktop - Probably
28
+ 6379/tcp Redis - Probably
29
+ 8025/tcp Docker Desktop http://localhost:8025 Probably
30
+ 49470/tcp Visual Studio Code (Node.js) - Probably
31
+ 51061/tcp macOS Handoff - Better not
32
+ ╭──────────────────────────────────────────────────────────────────────────────╮
33
+ │ Port 3000 · Next.js (shop) - a web server │
34
+ │ Point a browser at it - that is what it is there for. │
35
+ │ Project shop │
36
+ │ Open http://localhost:3000 │
37
+ │ Started by you (slashui) · node · pid 41822 │
38
+ │ Close it Yes - yours, and as easy to start again as it was to start │
39
+ │ Afterwards Start it again with your dev command, usually `npm run dev`. │
40
+ ╰──────────────────────────────────────────────────────────────────────────────╯
41
+ ↑↓ move · / find · x close it · r refresh · u udp · d details · m advanced · q …
42
+ ```
43
+
44
+ Every row says something the process name does not. The process behind
45
+ `Visual Studio Code` is called `Code Helper`, and the one behind `macOS
46
+ Handoff` is called `rapportd`. Neither name would have told you anything, which
47
+ is the point: when nothing at all can be worked out, the column says `-` rather
48
+ than repeating the process name back at you.
49
+
50
+ Press `m` for advanced mode, which trades the explanations for the facts that
51
+ tell two identical-looking dev servers apart:
52
+
53
+ ```
54
+ slash-port 8/8 tcp · advanced
55
+ PORT PID USER PROCESS ADDRESS DESCRIPTION
56
+ 22/tcp 947 root sshd * OpenSSH server [protected]
57
+ 3000/tcp 41822 slashui node * Next.js (shop)
58
+ 5173/tcp 41905 slashui node * Vite dev server (admin)
59
+ 5432/tcp 39044 slashui com.docker.backend * Docker Desktop
60
+ 6379/tcp 788 slashui redis-server 127.0.0.1 Redis
61
+ 8025/tcp 39044 slashui com.docker.backend * Docker Desktop
62
+ 49470/tcp 1737 slashui Code Helper 127.0.0.1 Visual Studio Code (Node.js)
63
+ 51061/tcp 694 slashui rapportd * macOS Handoff
64
+ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
65
+ │ Process node · pid 41822 · parent 1204 zsh │
66
+ │ User slashui │
67
+ │ Listening * · TCP · IPv4 │
68
+ │ Clients 3 connections open │
69
+ │ Running 2h 11m (since 14:02) │
70
+ │ Memory 431 MB · 0.4% CPU │
71
+ │ Directory /Users/slashui/code/shop │
72
+ │ Command node /Users/slashui/code/shop/node_modules/.bin/next dev │
73
+ │ Kill Yes - yours, and as easy to start again as it was to start. Start it again with your … │
74
+ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
75
+ ↑↓/jk move · PgUp/PgDn/g/G jump · / filter · x kill · r rescan · u udp · d detail · m beginner · q …
31
76
  ```
32
77
 
33
78
  ## Install
@@ -47,7 +92,7 @@ Requires Node 22 or newer. Works on Linux, macOS, and Windows.
47
92
  ### Updating
48
93
 
49
94
  The current release is
50
- <!-- release:version -->0.2.1<!-- /release:version -->. To see what you have,
95
+ <!-- release:version -->0.3.0<!-- /release:version -->. To see what you have,
51
96
  and what is published:
52
97
 
53
98
  ```sh
@@ -90,15 +135,76 @@ reading before you take it.
90
135
  ## Use
91
136
 
92
137
  ```sh
93
- slash-port # the interactive list
138
+ slash-port # the interactive list, in beginner mode
139
+ slash-port --advanced # the same list, with the full detail
94
140
  slash-port 3000 # open on port 3000
95
141
  slash-port 3xxx # every port from 3000 to 3999
96
142
  slash-port 3000:3005 # every port in that range
97
143
  slash-port --plain # a plain table, for a pipe or a script
98
144
  slash-port --json # the same data as JSON
99
145
  slash-port --udp # include UDP as well as TCP
146
+ slash-port --docker # name the container behind a published port
100
147
  ```
101
148
 
149
+ ### Beginner and advanced
150
+
151
+ There are two modes, and **beginner is the default**. The person who does not
152
+ know what took port 3000 is the person who went looking for a tool that would
153
+ tell them; anyone who already knows can say `--advanced` once, or set
154
+ `SLASH_PORT_MODE=advanced` and never say it again. `m` switches between them
155
+ at any time, and `d` hides the panel in either.
156
+
157
+ | | Beginner | Advanced |
158
+ | --- | --- | --- |
159
+ | Columns | Port, what it is, where to open it, whether to close it | Port, pid, user, process, address, description |
160
+ | 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 |
161
+ | 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 |
162
+ | Confirmation | Says what closing it costs and how to undo it | Names the signal |
163
+ | Cost | One scan | One scan, plus a lookup for the row under the cursor |
164
+
165
+ Advanced mode's extra facts are fetched for the selected row only. A machine
166
+ with four hundred listening sockets would otherwise pay four hundred times over
167
+ for facts you are reading one row at a time.
168
+
169
+ ### Docker
170
+
171
+ A published container port shows as `Docker Desktop`, which is true and no help
172
+ at all - and the beginner panel says so rather than leaving you to wonder where
173
+ the name went:
174
+
175
+ ```
176
+ ╭──────────────────────────────────────────────────────────────────────────────╮
177
+ │ Port 5432 · Docker Desktop - a container port │
178
+ │ Publishing a port on behalf of a container. │
179
+ │ Container not looked up - re-run with --docker to name it │
180
+ │ Started by you (slashui) · com.docker.backend · pid 39044 │
181
+ │ Close it Probably - yours, but something may be relying on it │
182
+ │ Afterwards Stopping the container that owns the port is the change you prob… │
183
+ ╰──────────────────────────────────────────────────────────────────────────────╯
184
+ ```
185
+
186
+ `--docker` asks the local engine which container is behind the port. The image
187
+ is read the same way a command line is, so `postgres:16` reports PostgreSQL and
188
+ is treated with the care a database deserves, and the compose project becomes
189
+ the hint - which is how two Supabase stacks on 5432 and 54322 stop being
190
+ interchangeable:
191
+
192
+ ```
193
+ ╭──────────────────────────────────────────────────────────────────────────────╮
194
+ │ Port 5432 · PostgreSQL in Docker (shop) - a database │
195
+ │ The container shop-db, from the shop compose project, running postgres:16-a… │
196
+ │ Container shop │
197
+ │ Started by you (slashui) · com.docker.backend · pid 39044 │
198
+ │ Close it Probably - stop the container instead: `docker stop shop-db` │
199
+ │ Afterwards Bring it back with `docker compose up -d db`. │
200
+ ╰──────────────────────────────────────────────────────────────────────────────╯
201
+ ```
202
+
203
+ It stays off until you ask for it. Reading two local tables and stopping is the
204
+ property this tool is built around, and a nicer default is not worth trading it
205
+ for. `SLASH_PORT_DOCKER=1` turns it on for good if you would rather not type
206
+ it, and `--no-docker` overrules that for one run.
207
+
102
208
  ### Naming ports
103
209
 
104
210
  `--port` and the interactive filter take the same three forms:
@@ -140,6 +246,8 @@ There is no flag combination that kills something without naming it first.
140
246
  | `x` or `Enter` | Kill the selected port |
141
247
  | `r` | Rescan |
142
248
  | `u` | Show UDP as well as TCP |
249
+ | `m` | Switch between beginner and advanced |
250
+ | `d` | Show or hide the detail panel |
143
251
  | `q` | Quit |
144
252
 
145
253
  In the confirmation dialog: `y` sends SIGTERM, `f` forces with SIGKILL, `n`
@@ -150,7 +258,11 @@ cancels. The kill key is deliberately not next to a navigation key.
150
258
  | Option | Does |
151
259
  | --- | --- |
152
260
  | `-p`, `--port <ports>` | Only these ports: `3000`, `3xxx`, or `3000:3005` |
261
+ | `--beginner` | Explain each port in plain language. The default |
262
+ | `--advanced` | Show the full detail instead of the explanations |
263
+ | `--mode <name>` | `beginner` or `advanced`. `SLASH_PORT_MODE` sets the default |
153
264
  | `-u`, `--udp` | Include UDP sockets |
265
+ | `--docker` | Ask the local Docker socket which container holds a port. Off by default; `SLASH_PORT_DOCKER=1` sets the default |
154
266
  | `--json` | Print JSON and exit |
155
267
  | `--plain` | Print a plain table and exit |
156
268
  | `--kill` | Kill the process on `--port`. Requires `--yes` |
@@ -162,6 +274,19 @@ cancels. The kill key is deliberately not next to a navigation key.
162
274
  | `-h`, `--help` | Show help |
163
275
  | `-v`, `--version` | Show the version |
164
276
 
277
+ ### Output for scripts
278
+
279
+ `--json` is the stable machine surface. Fields are added over time and never
280
+ repurposed, so a `jq` expression written against an old version keeps working.
281
+ `description` is `null` rather than a copy of `process` when nothing could be
282
+ identified, which is the one thing worth knowing before parsing it: absence is
283
+ reported as absence.
284
+
285
+ `--plain` keeps the same six columns in both modes and always will, so anything
286
+ already splitting that output keeps working. A mode only ever appends a column
287
+ on the end - what closing it would mean in beginner mode, the full command line
288
+ in advanced.
289
+
165
290
  ### Exit codes
166
291
 
167
292
  The same codes across every `slash-*` tool, so a script that wraps one can wrap
@@ -204,6 +329,13 @@ are fixed rather than configurable:
204
329
  init process, `sshd` - killing it locks you out of a remote machine - macOS
205
330
  and Windows session processes, `slash-port` itself, and the shell that
206
331
  launched it.
332
+ - **Whether closing it is a good idea is settled before you decide.** Every row
333
+ carries a verdict - `Yes`, `Probably`, `Better not`, `No`, `Needs sudo` -
334
+ worked out from what it is, who owns it, and whether a guardrail already
335
+ refuses it. The verdict is a word in a column, never a colour alone.
336
+ - **The confirmation is never the thing that gets truncated.** On a terminal
337
+ too short to show it and the list behind it, the list gives way; a question
338
+ you cannot read is a question you cannot answer.
207
339
  - **SIGTERM before SIGKILL.** A process that ignores SIGTERM is reported as
208
340
  having survived. Escalating is a second, deliberate action, never automatic.
209
341
  - **A process that has already exited is never signalled**, because by then its
@@ -216,9 +348,17 @@ do the same thing.
216
348
 
217
349
  ## Privacy
218
350
 
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.
351
+ `slash-port` makes no network connections at any point. By default it reads
352
+ the local socket table and the local process table, and asks nothing else on
353
+ the machine anything either. There is no telemetry, no update check, and no
354
+ configuration file.
355
+
356
+ `--docker` is the single exception, and it is off until you ask for it. It
357
+ reads the local Docker socket - a file on this machine, the same as
358
+ `/proc/net/tcp` is - to name the container behind a published port. A
359
+ `DOCKER_HOST` pointing at another machine over TCP is ignored rather than
360
+ connected to. `SLASH_PORT_DOCKER=1` turns it on for good if you would rather
361
+ not type it; `--no-docker` still overrules that for one run.
222
362
 
223
363
  ## Terminal behaviour
224
364
 
@@ -233,19 +373,50 @@ telemetry, no update check, and no configuration file.
233
373
  - The list is windowed to the visible rows, so a machine with four hundred
234
374
  listening sockets renders a screenful, not four hundred lines.
235
375
  - 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.
376
+ and values that are cut are marked with an ellipsis. Beginner mode keeps all
377
+ four of its columns down to eighty, because the fourth is the answer.
378
+ - A column that has nothing to show stands down rather than printing a column
379
+ of dashes: `OPEN AT` appears when the rows on screen have URLs.
237
380
 
238
381
  ## How it identifies a process
239
382
 
240
- Three sources, in priority order:
383
+ The description column exists to say something the process column did not. So
384
+ the first rule is that it never repeats the process name: when nothing could be
385
+ worked out, it says `-`, because "slash-port has no idea" is a fact and
386
+ `figma_agent` beside `figma_agent` is a column doing nothing.
387
+
388
+ What it consults, in priority order:
241
389
 
242
390
  1. **The command line.** Specific frameworks are matched before the runtimes
243
391
  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.
392
+ 2. **The container**, if you passed `--docker`. The local engine is asked which
393
+ container publishes the port, and the image is then read like a command
394
+ line, so `postgres:16` reports "PostgreSQL in Docker" and is treated with
395
+ the care a database deserves. The compose project - or the container name
396
+ when there is no project - becomes the hint, which is how `5432` and `54322`
397
+ stop being interchangeable. Without the flag a published port reports
398
+ `Docker Desktop`, and beginner mode says so rather than leaving you to
399
+ wonder why the name is missing.
400
+ 3. **The application.** The bundle or install directory the binary sits in,
401
+ so `Code Helper` reports Visual Studio Code and `figma_agent` reports Figma.
402
+ The outermost bundle wins, and a vendor directory beats the bundle inside it.
403
+ 4. **The project.** The directory above `node_modules` in the command line, so
404
+ two Vite servers on 5173 and 5174 can be told apart. A directory that only
405
+ names a convention - `lib`, `src`, `bin` - is passed over for the script
406
+ itself, which is why `…/google-cloud-sdk/lib/gcloud.py` reads as `gcloud`.
407
+ 5. **A well-known port registry**, for processes that could not be identified
408
+ at all - mostly other users'. Generic entries are demoted rather than
409
+ suppressed: "dev server" loses to anything specific, and beats saying
410
+ nothing.
411
+ 6. **The shape of the path.** A binary under `/usr/libexec` is a system service
412
+ whoever wrote it, which is worth more than its own name repeated back.
413
+
414
+ Beginner mode adds one more question on top of all that: whether closing it is
415
+ a good idea. That answer folds together what kind of thing it is, whether you
416
+ own it, and whether a guardrail already refuses it - and the last two win,
417
+ because they are facts about this machine rather than guesses about software. A
418
+ Postgres you do not own is `Needs sudo` whatever anyone thinks of closing
419
+ databases.
249
420
 
250
421
  Per platform:
251
422
 
@@ -258,14 +429,22 @@ Per platform:
258
429
  - **Windows** uses `netstat -ano` and `tasklist`, which exist on every edition
259
430
  and avoid PowerShell's startup cost.
260
431
 
432
+ Advanced mode's per-row lookups follow the same rule of asking the cheapest
433
+ thing that can answer: `/proc` on Linux with no subprocess at all, `ps` and
434
+ `lsof` on macOS, and on Windows only what `tasklist` and `netstat` already
435
+ know. Parents, working directories, and start times need WMI or PowerShell
436
+ there, which cost about a second each, so those lines are left out rather than
437
+ paid for. A platform that cannot answer omits the line; it never guesses.
438
+
261
439
  ## Not built yet
262
440
 
263
441
  Deliberate omissions, listed so you know they are choices rather than
264
442
  oversights:
265
443
 
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.
444
+ - **Docker awareness by default.** `--docker` names the container behind a
445
+ published port, and it stays opt-in. Reading two local tables and stopping is
446
+ the property this tool is built around, and it is not worth trading for a
447
+ nicer default.
269
448
  - **Process trees.** Killing a dev server sometimes leaves children behind. A
270
449
  `--tree` option would signal the whole group.
271
450
  - **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
  }