buninu 0.4.1 → 0.4.2
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/CHANGELOG.md +35 -0
- package/README.md +86 -5
- package/apps/bunmsh/CHANGELOG.md +176 -0
- package/apps/bunmsh/LICENSE-MICRO +58 -0
- package/apps/bunmsh/README.md +243 -2
- package/apps/bunmsh/help/README.md +292 -0
- package/apps/bunmsh/help/curl.md +181 -0
- package/apps/bunmsh/help/kill.md +16 -0
- package/apps/bunmsh/help/pspa.md +38 -0
- package/apps/bunmsh/help/pspac.md +57 -0
- package/apps/bunmsh/package.json +6 -2
- package/apps/bunmsh/src/completion.js +116 -0
- package/apps/bunmsh/src/curl.js +1191 -0
- package/apps/bunmsh/src/main.js +74 -0
- package/apps/bunmsh/src/shell.js +346 -5
- package/apps/bunmsh/test/curl.test.js +335 -0
- package/apps/bunmsh/test/reference.test.js +127 -1
- package/apps/bunmsh/test/shell.test.js +316 -2
- package/package.json +1 -1
package/apps/bunmsh/README.md
CHANGED
|
@@ -196,6 +196,87 @@ the right. Neither form invokes Bun Shell by itself; their purpose here is
|
|
|
196
196
|
only to enter the highest-priority evaluator and then execute unrestricted
|
|
197
197
|
JavaScript.
|
|
198
198
|
|
|
199
|
+
#### Use `$` to read and write shell variables
|
|
200
|
+
|
|
201
|
+
Inside JavaScript mode, `$` is the shell's own variable table — the live
|
|
202
|
+
object, not a copy — so the two languages share one set of variables instead of
|
|
203
|
+
passing strings between them:
|
|
204
|
+
|
|
205
|
+
```sh
|
|
206
|
+
Bun.e, $.HOME # read
|
|
207
|
+
Bun.e, $.PATH.split(":").length # read, as a JavaScript value
|
|
208
|
+
Bun.e; void ($.TAG = "v" + Date.now())
|
|
209
|
+
echo "$TAG" # the shell sees what JavaScript wrote
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
A shell variable is visible to JavaScript whether or not it was exported, and a
|
|
213
|
+
name JavaScript writes behaves like any other shell variable from that point
|
|
214
|
+
on, including being inherited by external child processes. `delete $.NAME`
|
|
215
|
+
unsets one, and `Object.keys($)` enumerates them.
|
|
216
|
+
|
|
217
|
+
An assignment is an expression, so its value is printed like any other result.
|
|
218
|
+
Wrap it in `void (...)` — as above — when the assignment is the point and the
|
|
219
|
+
echo is not.
|
|
220
|
+
|
|
221
|
+
**Everything the shell put there is a string.** A shell has no other type, so
|
|
222
|
+
`+` concatenates where you may have meant arithmetic — convert first:
|
|
223
|
+
|
|
224
|
+
```sh
|
|
225
|
+
X=3
|
|
226
|
+
Bun.e, $.X + 1 # "31"
|
|
227
|
+
Bun.e, Number($.X) + 1 # 4
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
The reverse direction does not convert for you either: `$.N = 42` stores the
|
|
231
|
+
number 42 in the table. The shell and any child process still read `42`,
|
|
232
|
+
because they stringify at their own boundary, but JavaScript now sees a number
|
|
233
|
+
under that name and a string under every name the shell set — so the same
|
|
234
|
+
expression means two different things depending on who last wrote the variable:
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
X=3
|
|
238
|
+
Bun.e; void ($.N = 42)
|
|
239
|
+
Bun.e, [$.X + 1, $.N + 1] # [ "31", 43 ]
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Assign strings (`$.N = String(count)`) to keep one rule for every name.
|
|
243
|
+
|
|
244
|
+
Two things to know:
|
|
245
|
+
|
|
246
|
+
- `$` is bound only inside JavaScript mode, and only shadows the bare name.
|
|
247
|
+
`Bun.$`, Bun Shell's own API, is reached through the `Bun` object and is
|
|
248
|
+
unaffected.
|
|
249
|
+
- Writing through `$` mutates the table directly, so it bypasses `readonly`.
|
|
250
|
+
`readonly R=locked` still refuses `R=other` from the shell, but
|
|
251
|
+
`$.R = "other"` goes through. That makes it an escape hatch, and a way to
|
|
252
|
+
break an invariant the shell was asked to hold.
|
|
253
|
+
|
|
254
|
+
#### One line at a time
|
|
255
|
+
|
|
256
|
+
JavaScript mode runs the line it was given. It does not continue across lines
|
|
257
|
+
the way a shell command does, because the shell's continuation marker is not
|
|
258
|
+
JavaScript: a bare `\` at the end of a line is a syntax error there, not a
|
|
259
|
+
request for another line, so the prompt does not ask for one.
|
|
260
|
+
|
|
261
|
+
The exception is the place where JavaScript has a line continuation of its
|
|
262
|
+
own — inside a string or template literal — and there it works, because the
|
|
263
|
+
prompt keeps collecting lines while the quote is open and JavaScript joins them
|
|
264
|
+
itself:
|
|
265
|
+
|
|
266
|
+
```sh
|
|
267
|
+
Bun.e, "abc\
|
|
268
|
+
def"
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
```text
|
|
272
|
+
abcdef
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
An unbalanced bracket does not continue: the shell's parser is looking for
|
|
276
|
+
shell syntax, not JavaScript's, so `Bun.e; function f() {` runs as typed and
|
|
277
|
+
reports its own syntax error. For code that spans lines, put it in a file and
|
|
278
|
+
`import` it, or keep the statements on one line separated by `;`.
|
|
279
|
+
|
|
199
280
|
#### Use `Bun.sha` as a shared area (hack)
|
|
200
281
|
|
|
201
282
|
`Bun.sha` is normally Bun's SHA hashing function. JavaScript functions are
|
|
@@ -333,6 +414,61 @@ tab r # back to ~/project/src
|
|
|
333
414
|
|
|
334
415
|
## Special Interactions
|
|
335
416
|
|
|
417
|
+
### Completion and ghost suggestions
|
|
418
|
+
|
|
419
|
+
Tab completes the word being typed, and a dim **ghost** shows the first match
|
|
420
|
+
inline ahead of the cursor; the Right arrow accepts it. What is offered depends
|
|
421
|
+
on where the cursor is:
|
|
422
|
+
|
|
423
|
+
| Where | Offered |
|
|
424
|
+
| --- | --- |
|
|
425
|
+
| A command name | Builtins, aliases, and executables on `PATH` |
|
|
426
|
+
| Inside `$(` | Command names again — a substitution starts a new command |
|
|
427
|
+
| A `$` being typed | Shell variable names |
|
|
428
|
+
| A JavaScript line | `$.` completes a variable name, a string literal a path |
|
|
429
|
+
| Anywhere else | Files and directories, and history for the ghost |
|
|
430
|
+
|
|
431
|
+
**Variables.** `$HO` suggests `$HOME`, and `${HO` suggests `${HOME}` — the
|
|
432
|
+
brace it opened is closed for it. `${#HO` works the same way. Names come from
|
|
433
|
+
the shell's own variable table, so unexported names and anything JavaScript
|
|
434
|
+
mode wrote through `$` are offered alongside the environment.
|
|
435
|
+
|
|
436
|
+
The suggestion follows the shell's own rules about when a `$` expands:
|
|
437
|
+
|
|
438
|
+
- It works wherever an expansion would: mid-word, on the right of an
|
|
439
|
+
assignment (`X=$HO`), inside double quotes, and where a command name would
|
|
440
|
+
go (`$ED`).
|
|
441
|
+
- Single quotes suppress it, because nothing expands inside them.
|
|
442
|
+
- Nothing is offered for the other things a `$` can start, since none of them
|
|
443
|
+
is a name in progress: `$(` (a command substitution), `$?`, `$1`, `$$`
|
|
444
|
+
(already complete), and `\$` (a literal dollar sign — the backslashes are
|
|
445
|
+
counted, so `\\$HO` does suggest).
|
|
446
|
+
- A bare `$` has no name to match on, so it ghosts nothing. Tab still lists
|
|
447
|
+
every variable, the way Tab on an empty word lists every file.
|
|
448
|
+
|
|
449
|
+
Where both could apply, history wins the ghost: it completes the whole line,
|
|
450
|
+
which reaches further than a single variable name.
|
|
451
|
+
|
|
452
|
+
**On a JavaScript line** — one starting with `Bun.`, the same test the
|
|
453
|
+
evaluator dispatches on — the line is read as JavaScript instead, because shell
|
|
454
|
+
word-splitting says nothing useful about it. Two things complete there:
|
|
455
|
+
|
|
456
|
+
```sh
|
|
457
|
+
Bun.e, $.HO # -> $.HOME
|
|
458
|
+
Bun.e, Bun.file("/tm # -> a path, completed inside the string
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
- After `$.`, shell variable names. A bare `$` completes nothing here: in
|
|
462
|
+
JavaScript it is the variable table itself, and a name only begins after the
|
|
463
|
+
dot.
|
|
464
|
+
- Inside an unclosed string literal — `"`, `'`, or a template — the text back
|
|
465
|
+
to the opening quote is completed as a path. No trailing space is needed to
|
|
466
|
+
make the completer see it, and nothing has to be trimmed back off afterwards.
|
|
467
|
+
- A template's `${...}` is code again, so `$.` completes inside it and the
|
|
468
|
+
path resumes after the closing brace.
|
|
469
|
+
- Where neither applies, only the history ghost is offered; shell completion
|
|
470
|
+
would just produce noise on a JavaScript line.
|
|
471
|
+
|
|
336
472
|
### Keyboard shortcuts
|
|
337
473
|
|
|
338
474
|
- `Ctrl-C`: Interrupts the current input or foreground operation and returns to
|
|
@@ -453,7 +589,7 @@ Run `builtin` with no arguments to print the registered names at runtime.
|
|
|
453
589
|
| `.`, `source` | `FILE [ARG ...]` |
|
|
454
590
|
| `realpath` | One or more paths |
|
|
455
591
|
| `umask` | No operand to display, or an octal mask |
|
|
456
|
-
| `kill` | `-l`, `-SIGNAL`, `-NUMBER` |
|
|
592
|
+
| `kill` | `-l`, `-SIGNAL`, `-NUMBER`; on Windows, where the runtime can only `TerminateProcess` a subset of signals and never reaches the children, a terminating signal is sent as `taskkill /PID PID /T /F` instead, while `-0` still probes through the runtime |
|
|
457
593
|
| `set` | No operand to list variables; `-- ARG ...` sets positional arguments |
|
|
458
594
|
| `time` | Command and arguments; reports `real` elapsed time in milliseconds, with each decimal magnitude group shown in a different color |
|
|
459
595
|
| `yes` | Optional output words; no flags |
|
|
@@ -661,6 +797,48 @@ unquoted `=on` / `=/index.html` / `=1` forms above work directly from a
|
|
|
661
797
|
shell, no manual `--define 'process.env.SERVE_AUTO_OPEN="/index.html"'`
|
|
662
798
|
quoting required.
|
|
663
799
|
|
|
800
|
+
### The `curl` command
|
|
801
|
+
|
|
802
|
+
`curl [options] URL...` transfers a URL over HTTP or HTTPS on top of Bun's own
|
|
803
|
+
`fetch`, so a device with no `curl` binary can still run the download and API
|
|
804
|
+
scripts that expect one. It is a PATH-fallback builtin: a real `curl` in
|
|
805
|
+
`PATH` wins unless it is invoked as `builtin curl ...`.
|
|
806
|
+
|
|
807
|
+
- A URL with no scheme gets one — `http://` normally, `https://` when the port
|
|
808
|
+
is `443`, or whatever `--proto-default` names — so `curl localhost:8080` and
|
|
809
|
+
`curl example.com/page` work as they do with the real curl.
|
|
810
|
+
- Downloads: `-o`, `-O`, `-J`, `--output-dir`, `--create-dirs`, `-a`, and
|
|
811
|
+
`-C -` resume through a `Range` request, appending on `206`, rewriting on a
|
|
812
|
+
`200` that ignored the range, and stopping cleanly on `416`.
|
|
813
|
+
- Requests: `-X`, `-H`, `-d`/`--data-raw`/`--data-binary`/`--data-ascii`,
|
|
814
|
+
`--data-urlencode`, `--json`, `-G`, `-F`/`--form-string`, `-T`, `-u`,
|
|
815
|
+
`--oauth2-bearer`, `-A`, `-e`, `-b`, `-r`, `--compressed`, and `-x`.
|
|
816
|
+
`@file` and `@-` read a body from a file or stdin.
|
|
817
|
+
- Responses: `-i`, `-I`, `-D`, `-w` with the usual `%{variable}` set, `-L`
|
|
818
|
+
with `--max-redirs` and the `301`/`302`/`303` POST-to-GET rule, `-f`,
|
|
819
|
+
`--fail-with-body`, `-k`, `-m`, `--connect-timeout`, and `--retry`.
|
|
820
|
+
- Reporting: `-s`, `-S`, `-v`, `-#`, and a curl-shaped progress meter, shown
|
|
821
|
+
only when the body is not being painted on the terminal.
|
|
822
|
+
- curl's exit codes are reproduced: `22` for `-f` on an HTTP error, `6` for an
|
|
823
|
+
unresolved host, `7` for a refused connection, `28` for a timeout, `47` for
|
|
824
|
+
too many redirects, `60` for a certificate problem, `2` for bad usage.
|
|
825
|
+
- Bodies are streamed, so `curl -N` on a server-sent-events endpoint prints
|
|
826
|
+
each chunk as it arrives, and a large download never buffers in memory.
|
|
827
|
+
|
|
828
|
+
Enough to drive a JSON API:
|
|
829
|
+
|
|
830
|
+
```sh
|
|
831
|
+
curl -sS https://api.openai.com/v1/chat/completions \
|
|
832
|
+
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
|
833
|
+
-H 'Content-Type: application/json' \
|
|
834
|
+
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"hi"}]}'
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
Response headers come from `fetch`, which lower-cases them and hides the
|
|
838
|
+
negotiated HTTP version, so `-i`/`-I`/`-v` rebuild the conventional casing and
|
|
839
|
+
write `HTTP/1.1` status lines; Bun also adds a `Connection: keep-alive`
|
|
840
|
+
request header of its own. `builtin curl --help` documents the rest.
|
|
841
|
+
|
|
664
842
|
### PATH-fallback builtins
|
|
665
843
|
|
|
666
844
|
Fallback builtins normally let an executable in `PATH` win. To use the fancy
|
|
@@ -670,6 +848,7 @@ aliases that explicitly select the builtin commands:
|
|
|
670
848
|
```sh
|
|
671
849
|
alias cat='builtin catfancy'
|
|
672
850
|
alias ls='builtin lsfancy'
|
|
851
|
+
alias ps='builtin pspac'
|
|
673
852
|
```
|
|
674
853
|
|
|
675
854
|
After that, `cat README.md` renders Markdown with ANSI styling and terminal
|
|
@@ -701,10 +880,13 @@ hyperlinks, while `ls` uses the emoji and terminal-width-aware listing. Use
|
|
|
701
880
|
| `ln` | `-s`, `-f`, `-T`, combinable (including `-sfT`) |
|
|
702
881
|
| `chmod` | Octal modes, `+x`, `a+x` |
|
|
703
882
|
| `uname` | `-a`, `-s`, `-n`, `-r`, `-v`, `-m`, `-p`, combinable (including `-mprs`); uses Node's OS APIs on Windows without `/proc` |
|
|
883
|
+
| `pspa` | Lists every process as a PID and its full command line, with no options; `ps -eo pid,args` passed through on POSIX, the same two columns queried from `Win32_Process` through PowerShell on Windows |
|
|
884
|
+
| `pspac` | The same listing, coloured: the PID as a number, and the command line highlighted as shell syntax with micro's `syntax/sh.yaml` rules and `colorschemes/monokai.micro` colours, plus a dimmed leading directory and the program's own name coloured as the command it is. Always colours, like `catfancy`; strip the colour and the output is `pspa`'s |
|
|
704
885
|
| `find` | Paths plus `-name`, `-iname`, `-path`, `-ipath`, `-type f/d/l`, `-mindepth`, `-maxdepth`, `-print`, `-print0`, `!`/`-not`, `-exec COMMAND {} \;`, `-exec COMMAND {} +`; regular builtin on Windows, PATH fallback elsewhere |
|
|
705
886
|
| `bunmsh` | Forwards all following arguments to this bunmsh entry point |
|
|
706
887
|
| `bun` | Forwards all following arguments to the active Bun runtime |
|
|
707
888
|
| `serve` | Auto-open, minapk WebView, and high-entropy random-URL flags; see [The `serve` command](#the-serve-command) above |
|
|
889
|
+
| `curl` | HTTP/HTTPS transfers on Bun's `fetch`, with automatic scheme guessing; `-o`, `-O`, `-J`, `--output-dir`, `--create-dirs`, `-a`, `-C`, `-D`, `-i`, `-I`, `-w`, `-X`, `-H`, `-d`, `--data-raw`, `--data-binary`, `--data-ascii`, `--data-urlencode`, `--json`, `-G`, `-F`, `--form-string`, `-T`, `-u`, `--oauth2-bearer`, `-A`, `-e`, `-b`, `-r`, `--compressed`, `-x`, `-L`, `--location-trusted`, `--max-redirs`, `-f`, `--fail-with-body`, `-k`, `-m`, `--connect-timeout`, `--retry` and friends, `-s`, `-S`, `-v`, `-#`, `--no-progress-meter`, `-V`, `--url`, `--proto-default`, combinable short clusters (`-kLO`, `-fsSL`, `-kfsS`, `-#k`); TLS-material and connection-tuning options are parsed and ignored; see [The `curl` command](#the-curl-command) above |
|
|
708
890
|
| `ls`, `lsfancy` | The `ls` fallback is `lsfancy`: emoji and terminal-width-aware directory listing; `-a`, `-A`, `-d`, `-l`, `-h`, `-t`, `-r`, `-R`, `-S`, `-1`, `-F`, combinable (including `-lh`, `-ltr`, and `-lSF`); `-l` shows a symlink's target (`link -> target`, including a broken one), and a symlink whose target can't be resolved (missing, or a cycle) gets a 🚫 icon instead of 🔗; `-F` appends a classify suffix (`/` directory, `@` symlink, `*` executable, `=` socket, `\|` FIFO); always reads the directory without using the completion cache |
|
|
709
891
|
| `lsbun` | Bun Shell's own `ls`, kept reachable under this name now that the `ls` fallback is `lsfancy`; currently implements `-a`, `-A`, `-d`, `-l`, `-R` |
|
|
710
892
|
| `mv` | Bun Shell currently accepts `-f`, `-h`, `-i`, `-n`, `-v`, but they do not change its behaviour; notably, `-i` and `-n` do not prevent overwriting |
|
|
@@ -742,11 +924,17 @@ detailed compatibility snapshot.
|
|
|
742
924
|
- Regular builtins, system-command-first fallback builtins, Bun Shell fallbacks,
|
|
743
925
|
and explicit lookup through `command`, `builtin`, `whence`, `type`, and
|
|
744
926
|
`which`.
|
|
745
|
-
- Interactive history import/save/recall, command
|
|
927
|
+
- Interactive history import/save/recall, command, file, and shell-variable
|
|
928
|
+
completion, ghost
|
|
746
929
|
suggestions, cwd tabs, keyboard shortcuts, optional mouse interactions,
|
|
747
930
|
fancy directory listings, and a `PS2` continuation prompt while a
|
|
748
931
|
here-document, an open quote/substitution, or an unfinished compound
|
|
749
932
|
command is still being typed.
|
|
933
|
+
- A `curl` fallback built on `fetch`, covering downloads with resume, JSON and
|
|
934
|
+
form request bodies, redirects, timeouts, retries, `--write-out` reporting,
|
|
935
|
+
and curl's exit codes.
|
|
936
|
+
- A `pspa` process listing that works the same way on POSIX and Windows, and a
|
|
937
|
+
`pspac` that colours it as shell syntax.
|
|
750
938
|
- Linux, Android/Termux, macOS, and Windows-aware paths, plus standalone builds
|
|
751
939
|
and dynamic-linker re-execution support.
|
|
752
940
|
|
|
@@ -772,6 +960,17 @@ Both commands read their embedded copy first when running a standalone
|
|
|
772
960
|
executable, then fall back to `README.md` or `CHANGELOG.md` in the repository
|
|
773
961
|
during development.
|
|
774
962
|
|
|
963
|
+
Every builtin's `--help` page lives in `help/`, and `help/README.md` is the
|
|
964
|
+
concatenation of all of them. Regenerate it with the shell's own `cat` after
|
|
965
|
+
adding or editing a page:
|
|
966
|
+
|
|
967
|
+
```sh
|
|
968
|
+
bun run genallhelp
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
which runs `builtin cat --exclude help/README.md help/*.md` and writes the
|
|
972
|
+
result back over `help/README.md`.
|
|
973
|
+
|
|
775
974
|
## Standalone executable
|
|
776
975
|
|
|
777
976
|
Build a single-file executable for the current platform:
|
|
@@ -799,3 +998,45 @@ The original bunmsh JavaScript implementation is released under the
|
|
|
799
998
|
|
|
800
999
|
mksh is a separate upstream project and is **not** relicensed under MIT. Its
|
|
801
1000
|
complete licence terms remain in [LICENSE-MKSH](LICENSE-MKSH).
|
|
1001
|
+
|
|
1002
|
+
### Syntax highlighting
|
|
1003
|
+
|
|
1004
|
+
The shell-syntax colouring `pspac` applies to the COMMAND column follows
|
|
1005
|
+
`runtime/syntax/sh.yaml` from [micro](https://github.com/zyedidia/micro), the
|
|
1006
|
+
Go terminal editor. Nothing is bundled: its rules — the keyword,
|
|
1007
|
+
command-name, flag, variable, string, and comment patterns, the word lists
|
|
1008
|
+
behind them, and the order they resolve in — were transcribed into
|
|
1009
|
+
`src/shell.js`. Micro's syntax files are MIT ("Expat"), Copyright (c) 2020:
|
|
1010
|
+
Zachary Yedidia, et al.; micro's own `syntax/README.md` records that they
|
|
1011
|
+
originate from Nano's [`nanorc`](https://github.com/scopatz/nanorc)
|
|
1012
|
+
collection.
|
|
1013
|
+
|
|
1014
|
+
The colours those classes are painted in are the colour-links of micro's
|
|
1015
|
+
`runtime/colorschemes/monokai.micro` — micro itself is MIT, Copyright (c)
|
|
1016
|
+
2016-2020: Zachary Yedidia, et al. — which renders the Monokai palette created
|
|
1017
|
+
by Wimer Hazenberg. `catfancy` takes five of the same colour-links for its
|
|
1018
|
+
JSON keys, strings, numbers, escapes, and constants, so both commands read as
|
|
1019
|
+
one scheme rather than two.
|
|
1020
|
+
|
|
1021
|
+
Micro's terms are in [LICENSE-MICRO](LICENSE-MICRO); upstream they are
|
|
1022
|
+
`runtime/syntax/LICENSE` and `LICENSE` in
|
|
1023
|
+
[zyedidia/micro](https://github.com/zyedidia/micro), which is where to trace
|
|
1024
|
+
either of them from.
|
|
1025
|
+
|
|
1026
|
+
### Licences in a compiled executable
|
|
1027
|
+
|
|
1028
|
+
`LICENSE`, `LICENSE-MKSH`, and `LICENSE-MICRO` are packaged assets, so a
|
|
1029
|
+
standalone build carries them inside the binary rather than leaving the notices
|
|
1030
|
+
behind in the repository. Reading them back depends on which asset back end the
|
|
1031
|
+
build used:
|
|
1032
|
+
|
|
1033
|
+
```sh
|
|
1034
|
+
./bmsh --assets-extract # tar back end (the default)
|
|
1035
|
+
./bmsh -cc builtin serve 'B:/~BUN' # ASSETS_BUNFS=1 build
|
|
1036
|
+
```
|
|
1037
|
+
|
|
1038
|
+
[`--assets-extract`](#standalone-executable) writes every asset beside the
|
|
1039
|
+
executable, licences included, under `assets/bunmsh@<version>/`. For a bunfs
|
|
1040
|
+
build, [serving `B:/~BUN`](#serving-a-folder-packed-into-the-executable)
|
|
1041
|
+
browses the binary's own virtual root, where the same files sit under
|
|
1042
|
+
`/assets/bunmsh@<version>/`.
|
|
@@ -370,6 +370,187 @@ Output:
|
|
|
370
370
|
```text
|
|
371
371
|
hello
|
|
372
372
|
```
|
|
373
|
+
## curl
|
|
374
|
+
|
|
375
|
+
Transfer a URL over HTTP or HTTPS, built on Bun's own `fetch`.
|
|
376
|
+
|
|
377
|
+
This is a **fallback builtin**: a real `curl` found on `PATH` always wins, so
|
|
378
|
+
scripts keep the system binary where there is one and still run on a device
|
|
379
|
+
that has none. `builtin curl` selects this implementation explicitly.
|
|
380
|
+
|
|
381
|
+
### Usage
|
|
382
|
+
|
|
383
|
+
```sh
|
|
384
|
+
curl [OPTIONS] URL...
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
A URL with no scheme gets one: `http://` by default, `https://` when the port
|
|
388
|
+
is `443`, or whatever `--proto-default` says. So `curl localhost:8080` and
|
|
389
|
+
`curl example.com/page` work the way they do with the real curl. Only `http`
|
|
390
|
+
and `https` are supported; anything else fails with exit code `1`.
|
|
391
|
+
|
|
392
|
+
### Options and forms
|
|
393
|
+
|
|
394
|
+
#### Output and files
|
|
395
|
+
|
|
396
|
+
- `-o, --output FILE`: Write the body to `FILE` instead of stdout. `-o -`
|
|
397
|
+
means stdout. Repeat it to pair one target with each URL, in order.
|
|
398
|
+
- `-O, --remote-name`: Save under the filename from the URL path.
|
|
399
|
+
- `--remote-name-all`: Treat every URL as if it had its own `-O`.
|
|
400
|
+
- `-J, --remote-header-name`: With `-O`, prefer the name in the
|
|
401
|
+
`Content-Disposition` header.
|
|
402
|
+
- `--output-dir DIR`: Write `-o`/`-O` files under `DIR`.
|
|
403
|
+
- `--create-dirs`: Create missing parent directories for the output file.
|
|
404
|
+
- `-a, --append`: Append to the output file instead of truncating it.
|
|
405
|
+
- `-C, --continue-at OFFSET|-`: Resume a partial download. `-` sizes the
|
|
406
|
+
existing file and asks for the rest with a `Range` header; the file is
|
|
407
|
+
appended to when the server answers `206`, and rewritten when it answers
|
|
408
|
+
`200` and ignored the range. A `416` answer means the local file is already
|
|
409
|
+
complete: nothing is written and the exit status is `0`.
|
|
410
|
+
- `-D, --dump-header FILE`: Write the response headers to `FILE` (`-` for
|
|
411
|
+
stdout).
|
|
412
|
+
- `-i, --include`: Print the response headers before the body. With `-L`,
|
|
413
|
+
every hop's headers are printed, as the real curl does.
|
|
414
|
+
- `-I, --head`: Send `HEAD` and print the response headers.
|
|
415
|
+
- `-w, --write-out FORMAT`: Print `FORMAT` after the transfer, with
|
|
416
|
+
`%{variable}` substitutions and `\n`, `\t`, `\r` escapes. `@FILE` (or `@-`)
|
|
417
|
+
reads the format from a file. Supported variables: `url`, `url_effective`,
|
|
418
|
+
`method`, `scheme`, `http_code`, `response_code`, `http_version`,
|
|
419
|
+
`num_redirects`, `num_headers`, `redirect_url`, `size_download`,
|
|
420
|
+
`size_upload`, `size_header`, `size_request`, `speed_download`,
|
|
421
|
+
`speed_upload`, `content_type`, `filename_effective`, `remote_ip`,
|
|
422
|
+
`remote_port`, `ssl_verify_result`, `exitcode`, `errormsg`, `time_total`,
|
|
423
|
+
`time_namelookup`, `time_connect`, `time_appconnect`, `time_pretransfer`,
|
|
424
|
+
`time_starttransfer`, `time_redirect`, `header_json`, `json`, `stdout`,
|
|
425
|
+
`stderr`.
|
|
426
|
+
|
|
427
|
+
#### Request shaping
|
|
428
|
+
|
|
429
|
+
- `-X, --request METHOD`: Set the request method.
|
|
430
|
+
- `-H, --header 'Name: value'`: Add or replace a header. `'Name;'` sends an
|
|
431
|
+
empty value; `'Name:'` removes a header that would otherwise be sent.
|
|
432
|
+
- `-d, --data DATA`, `--data-ascii DATA`: `POST` body; `@file` reads a file
|
|
433
|
+
(newlines stripped) and `@-` reads stdin. Repeats join with `&`.
|
|
434
|
+
- `--data-raw DATA`: Same, but `@` has no special meaning.
|
|
435
|
+
- `--data-binary DATA`: Same, but a `@file` is sent byte for byte.
|
|
436
|
+
- `--data-urlencode DATA`: Percent-encode before sending. Accepts `content`,
|
|
437
|
+
`=content`, `name=content`, `@file`, and `name@file`.
|
|
438
|
+
- `--json DATA`: `--data-binary` plus `Content-Type: application/json` and
|
|
439
|
+
`Accept: application/json`. `@file` and `@-` work here too.
|
|
440
|
+
- `-G, --get`: Move the data onto the query string and send `GET`.
|
|
441
|
+
- `-F, --form 'name=value'`, `--form-string`: `multipart/form-data`. `@file`
|
|
442
|
+
attaches a file, `<file` sends its contents as the field value, and
|
|
443
|
+
`;type=` / `;filename=` set the part's type and name.
|
|
444
|
+
- `-T, --upload-file FILE`: `PUT` the file (`-` reads stdin).
|
|
445
|
+
- `-u, --user USER[:PASSWORD]`: HTTP basic authentication.
|
|
446
|
+
- `--oauth2-bearer TOKEN`: Send `Authorization: Bearer TOKEN`.
|
|
447
|
+
- `-A, --user-agent NAME`: Override the default `curl/8.14.1`.
|
|
448
|
+
- `-e, --referer URL`: Send a `Referer` header; a trailing `;auto` is ignored.
|
|
449
|
+
- `-b, --cookie 'k=v'`: Send a `Cookie` header.
|
|
450
|
+
- `-r, --range RANGE`: Send `Range: bytes=RANGE`.
|
|
451
|
+
- `--compressed`: Ask for and transparently decode a compressed response.
|
|
452
|
+
Without it, no `Accept-Encoding` is negotiated, matching curl's default.
|
|
453
|
+
- `-x, --proxy URL`: Send the request through a proxy.
|
|
454
|
+
|
|
455
|
+
#### Redirects, failure, and timing
|
|
456
|
+
|
|
457
|
+
- `-L, --location`: Follow redirects. `301`/`302`/`303` turn a `POST` into a
|
|
458
|
+
`GET`; `307`/`308` keep the method and body. `Authorization` is dropped when
|
|
459
|
+
the host changes, unless `--location-trusted` is given.
|
|
460
|
+
- `--max-redirs N`: Cap the redirect chain (default 50, `-1` for unlimited).
|
|
461
|
+
Exceeding it fails with exit code `47`.
|
|
462
|
+
- `-f, --fail`: No body output on HTTP errors; exit `22` instead.
|
|
463
|
+
- `--fail-with-body`: Print the body and still exit `22`.
|
|
464
|
+
- `-k, --insecure`: Do not verify the server certificate.
|
|
465
|
+
- `-m, --max-time SECONDS`, `--connect-timeout SECONDS`: Abort a slow
|
|
466
|
+
transfer with exit code `28`.
|
|
467
|
+
- `--retry N`, `--retry-delay SECONDS`, `--retry-all-errors`,
|
|
468
|
+
`--retry-connrefused`: Retry connection failures, timeouts, and the
|
|
469
|
+
transient statuses `408`, `429`, `500`, `502`, `503`, and `504`.
|
|
470
|
+
|
|
471
|
+
#### Reporting
|
|
472
|
+
|
|
473
|
+
- `-s, --silent`: No progress meter and no error messages.
|
|
474
|
+
- `-S, --show-error`: Keep error messages while `-s` is in effect.
|
|
475
|
+
- `-#, --progress-bar`: A single-bar progress display instead of the meter.
|
|
476
|
+
- `--no-progress-meter`: Keep errors, drop the meter.
|
|
477
|
+
- `-v, --verbose`: Trace the request and response headers on stderr.
|
|
478
|
+
- `-V, --version`: Print the version banner.
|
|
479
|
+
|
|
480
|
+
Like the real curl, the progress meter is shown only when the body is *not*
|
|
481
|
+
being painted on the terminal — a `-o`/`-O` download or a redirected stdout
|
|
482
|
+
gets a meter, `curl URL` at a prompt does not.
|
|
483
|
+
|
|
484
|
+
#### Accepted and ignored
|
|
485
|
+
|
|
486
|
+
These are parsed so a script does not die on them, and then have no effect,
|
|
487
|
+
because `fetch` either handles that part itself or does not expose it:
|
|
488
|
+
`--cacert`, `--capath`, `-E/--cert`, `--key`, `--interface`, `--limit-rate`,
|
|
489
|
+
`--resolve`, `--connect-to`, `--unix-socket`, `--noproxy`, `--proxy-user`,
|
|
490
|
+
`--proxy-header`, `-n/--netrc`, `-c/--cookie-jar`, `-z/--time-cond`,
|
|
491
|
+
`-R/--remote-time`, `-N/--no-buffer` (output is always streamed anyway),
|
|
492
|
+
`-g/--globoff` (URL globbing is not performed, so `{}` and `[]` are already
|
|
493
|
+
literal), `-q/--disable`, `-4`, `-6`, `--http1.0`, `--http1.1`, `--http2`,
|
|
494
|
+
`--http3`, `--tlsv1.x`, `--tcp-nodelay`, `--keepalive`, `--anyauth`,
|
|
495
|
+
`--basic`, `--digest`, `-Z/--parallel`, `--max-filesize`, `--path-as-is`.
|
|
496
|
+
|
|
497
|
+
### Where it differs from the system curl
|
|
498
|
+
|
|
499
|
+
- `fetch` reports header names in lower case, so `-i`, `-I`, `-D`, and `-v`
|
|
500
|
+
rebuild the conventional capitalisation (`Content-Type`, `ETag`) and list
|
|
501
|
+
the headers in `fetch`'s order rather than the server's wire order.
|
|
502
|
+
- The negotiated HTTP version is not exposed, so status lines are written as
|
|
503
|
+
`HTTP/1.1`.
|
|
504
|
+
- Bun adds a `Connection: keep-alive` request header of its own.
|
|
505
|
+
- The progress meter is a look-alike: same columns, not the same arithmetic.
|
|
506
|
+
- URL globbing (`{a,b}`, `[1-10]`) is not implemented.
|
|
507
|
+
- `fetch` forbids a body on `GET` and `HEAD`, so `-X GET -d ...` sends the
|
|
508
|
+
request without the data; use `-G` to put it on the query string instead.
|
|
509
|
+
|
|
510
|
+
### Exit status
|
|
511
|
+
|
|
512
|
+
`0` on success, `1` unsupported protocol, `2` bad usage, `3` malformed URL,
|
|
513
|
+
`6` host not resolved, `7` connection failed, `22` HTTP error with `-f`,
|
|
514
|
+
`23` write error, `26` local file could not be read, `28` timeout,
|
|
515
|
+
`47` too many redirects, `56` connection reset, `60` certificate problem.
|
|
516
|
+
|
|
517
|
+
### Example
|
|
518
|
+
|
|
519
|
+
```sh
|
|
520
|
+
curl -s -o /dev/null -w '%{http_code} %{content_type}\n' example.com
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Output:
|
|
524
|
+
|
|
525
|
+
```text
|
|
526
|
+
200 text/html
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
The invocations a package script tends to use:
|
|
530
|
+
|
|
531
|
+
```sh
|
|
532
|
+
curl -kLO https://example.com/pkg.tar.gz
|
|
533
|
+
curl -C - -kLO https://example.com/pkg.tar.gz
|
|
534
|
+
curl -fsSL https://example.com/install.sh | sh
|
|
535
|
+
curl -#k https://example.com/pkg.tar.gz.sha256
|
|
536
|
+
curl -kfsS https://example.com/probe >/dev/null 2>/dev/null
|
|
537
|
+
curl localhost:8080
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
Calling a JSON API — enough for the OpenAI chat completions endpoint:
|
|
541
|
+
|
|
542
|
+
```sh
|
|
543
|
+
curl -sS https://api.openai.com/v1/chat/completions \
|
|
544
|
+
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
|
545
|
+
-H 'Content-Type: application/json' \
|
|
546
|
+
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"hi"}]}'
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
`--json` shortens that, and `-N` streaming responses arrive chunk by chunk:
|
|
550
|
+
|
|
551
|
+
```sh
|
|
552
|
+
curl -sN --json @request.json https://api.openai.com/v1/chat/completions
|
|
553
|
+
```
|
|
373
554
|
## cut
|
|
374
555
|
|
|
375
556
|
Select character positions.
|
|
@@ -742,6 +923,22 @@ kill [-SIGNAL] PID ...
|
|
|
742
923
|
|
|
743
924
|
- `-SIGNAL`: Select a signal by name or number; the default is SIGTERM.
|
|
744
925
|
- `-0`: Check whether a process can be signalled without sending a signal.
|
|
926
|
+
- `-l`: List the signal names this runtime knows.
|
|
927
|
+
|
|
928
|
+
### Windows
|
|
929
|
+
|
|
930
|
+
Windows has no signals to deliver. The runtime turns SIGTERM, SIGINT, and
|
|
931
|
+
SIGKILL into an unconditional `TerminateProcess`, refuses every other name,
|
|
932
|
+
and in no case touches the target's children. So on Windows every terminating
|
|
933
|
+
signal is sent as `taskkill /PID PID /T /F` instead: `/T` reaches the children
|
|
934
|
+
the runtime would leave running, and `/F` is what makes it work on a console
|
|
935
|
+
process that has no message loop to close.
|
|
936
|
+
|
|
937
|
+
The consequence is that the signal name is accepted but not honoured there —
|
|
938
|
+
`kill -HUP PID` terminates the process rather than failing, and nothing gets
|
|
939
|
+
the chance to shut down gracefully. `-0` is the exception: it asks whether the
|
|
940
|
+
PID exists without touching it, which `taskkill` cannot express, so it still
|
|
941
|
+
goes through the runtime.
|
|
745
942
|
|
|
746
943
|
### Example
|
|
747
944
|
|
|
@@ -1041,6 +1238,101 @@ Output:
|
|
|
1041
1238
|
```text
|
|
1042
1239
|
answer=42
|
|
1043
1240
|
```
|
|
1241
|
+
## pspa
|
|
1242
|
+
|
|
1243
|
+
List every process as a PID and its full command line.
|
|
1244
|
+
|
|
1245
|
+
### Usage
|
|
1246
|
+
|
|
1247
|
+
```sh
|
|
1248
|
+
pspa
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
It is a PATH-fallback builtin, so an executable named `pspa` found in `PATH`
|
|
1252
|
+
wins; `builtin pspa` selects this implementation. It takes no options — pipe
|
|
1253
|
+
it into `grep` to narrow the listing, and into `kill` to act on what you find.
|
|
1254
|
+
|
|
1255
|
+
[`pspac`](#pspac) prints the same listing with the PID and the command line
|
|
1256
|
+
coloured.
|
|
1257
|
+
|
|
1258
|
+
On POSIX systems this is `ps -eo pid,args`, and its output is passed through
|
|
1259
|
+
untouched. Reading `ps` over a pipe is also what keeps the command lines
|
|
1260
|
+
whole: procps truncates them at the terminal width when it is writing straight
|
|
1261
|
+
to a terminal.
|
|
1262
|
+
|
|
1263
|
+
Windows has no `ps`, so the same two columns are queried from
|
|
1264
|
+
`Win32_Process` through PowerShell and laid out the same way, with the image
|
|
1265
|
+
name standing in for a system process that reports no command line.
|
|
1266
|
+
|
|
1267
|
+
### Example
|
|
1268
|
+
|
|
1269
|
+
```sh
|
|
1270
|
+
pspa | grep bun
|
|
1271
|
+
```
|
|
1272
|
+
|
|
1273
|
+
Output:
|
|
1274
|
+
|
|
1275
|
+
```text
|
|
1276
|
+
1004 bun ./src/main.js
|
|
1277
|
+
1220 bun run dev
|
|
1278
|
+
```
|
|
1279
|
+
## pspac
|
|
1280
|
+
|
|
1281
|
+
The `pspa` process listing, coloured.
|
|
1282
|
+
|
|
1283
|
+
### Usage
|
|
1284
|
+
|
|
1285
|
+
```sh
|
|
1286
|
+
pspac
|
|
1287
|
+
```
|
|
1288
|
+
|
|
1289
|
+
It is a PATH-fallback builtin taking no options, and it lists exactly what
|
|
1290
|
+
[`pspa`](#pspa) lists — same processes, same two columns, same order. Strip
|
|
1291
|
+
the colour off its output and you have `pspa`'s byte for byte.
|
|
1292
|
+
|
|
1293
|
+
Like `catfancy`, it always colours rather than sniffing for a terminal, so the
|
|
1294
|
+
plain listing is always one command away: use `pspa` when the output is going
|
|
1295
|
+
somewhere that wants plain text.
|
|
1296
|
+
|
|
1297
|
+
### What gets coloured
|
|
1298
|
+
|
|
1299
|
+
The PID is painted as the number it is. The COMMAND column is a shell command
|
|
1300
|
+
line, so it is highlighted as one, using micro's `syntax/sh.yaml` rules and
|
|
1301
|
+
its `colorschemes/monokai.micro` colours — the same palette `catfancy` uses,
|
|
1302
|
+
so a command line reads the same here as in a previewed script:
|
|
1303
|
+
|
|
1304
|
+
- Command names, shell keywords, flags, numbers, variables, quoted strings,
|
|
1305
|
+
and comments each take their own colour.
|
|
1306
|
+
- Quoted strings and comments are regions, so a `#` inside an argument does
|
|
1307
|
+
not turn the rest of the line into a comment.
|
|
1308
|
+
- Later rules win, exactly as in the editor: `--cat` is a flag, not the
|
|
1309
|
+
coreutils `cat`.
|
|
1310
|
+
|
|
1311
|
+
Two things a process listing needs that a script does not:
|
|
1312
|
+
|
|
1313
|
+
- The directory in front of the program is dimmed. It is the part an absolute
|
|
1314
|
+
path buries the answer in, and `ps` prints a lot of it.
|
|
1315
|
+
- The program's own name is coloured as a command whether or not sh.yaml's
|
|
1316
|
+
word lists have heard of it — the file has to guess a command from a list,
|
|
1317
|
+
while here the first token is known to be one.
|
|
1318
|
+
|
|
1319
|
+
A kernel thread such as `[kworker/0:1]` has no program, path, or arguments to
|
|
1320
|
+
take apart, so it recedes as a whole.
|
|
1321
|
+
|
|
1322
|
+
### Example
|
|
1323
|
+
|
|
1324
|
+
```sh
|
|
1325
|
+
pspac
|
|
1326
|
+
```
|
|
1327
|
+
|
|
1328
|
+
Output:
|
|
1329
|
+
|
|
1330
|
+
```text
|
|
1331
|
+
PID COMMAND
|
|
1332
|
+
1 /init
|
|
1333
|
+
8824 /data/data/com.termux/files/usr/bin/bash -l
|
|
1334
|
+
8955 bun run dev
|
|
1335
|
+
```
|
|
1044
1336
|
## pwd
|
|
1045
1337
|
|
|
1046
1338
|
Print the active directory.
|