Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 65 additions & 52 deletions docs/runtime/repl.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@ bun repl
```

```txt
Welcome to Bun v1.3.3
Welcome to Bun v1.4.4
Type .copy [code] to copy to clipboard. .help for more info.

> 1 + 1
❯ 1 + 1
2
> const greeting = "Hello, Bun!"
undefined
> greeting
'Hello, Bun!'
❯ const greeting = "Hello, Bun!"
"Hello, Bun!"
❯ greeting
"Hello, Bun!"
```

The REPL prints the result of each input. A variable declaration prints the value of its last initializer.

With `NO_COLOR=1`, or when standard input or standard output is not a terminal, the prompt is `>`.

---

## Features
Expand All @@ -31,28 +35,31 @@ undefined
- **Persistent history** — The REPL saves history to `~/.bun_repl_history`. History persists across sessions.
- **Tab completion** — Press `Tab` to complete property names and REPL commands.
- **Multi-line input** — Unclosed brackets, braces, and parentheses automatically continue on the next line.
- **Node.js globals** — `require`, `module`, `__dirname`, and `__filename` are available, resolved relative to your current working directory.
- **Node.js globals** — `require` and `module` are available, resolved relative to the working directory that the REPL starts in.

---

## Special variables

The REPL exposes two special variables that update after each evaluation.
The REPL sets two special variables.

| Variable | Description |
| -------- | --------------------------------- |
| `_` | The result of the last expression |
| `_error` | The last error that was thrown |
| Variable | Description |
| -------- | ---------------------------------------- |
| `_` | The last result that was not `undefined` |
| `_error` | The last error that an input threw |

```txt
> 2 + 2
❯ 2 + 2
4
> _ * 10
❯ _ * 10
40
> JSON.parse("oops")
SyntaxError: JSON Parse error: Unexpected identifier "oops"
> _error
❯ JSON.parse("oops")
SyntaxError: JSON Parse error: Unexpected identifier "oops"
at <anonymous> ([repl]:4:22)
at [repl]:6:3

❯ _error.message
"JSON Parse error: Unexpected identifier \"oops\""
```

---
Expand All @@ -62,11 +69,11 @@ SyntaxError: JSON Parse error: Unexpected identifier "oops"
You can `await` any expression directly at the prompt.

```txt
> await fetch("https://api.github.com/repos/oven-sh/bun").then(r => r.json()).then(r => r.stargazers_count)
81234
> const response = await fetch("https://example.com")
❯ await Bun.sleep(1000)
undefined
> response.status
❯ const status = await fetch("https://bun.com").then(response => response.status)
200
❯ status
200
```

Expand All @@ -77,12 +84,12 @@ undefined
Like Bun's runtime, the REPL accepts both `require` and `import`: mix ES modules and CommonJS freely at the prompt. Module resolution uses the same rules as `bun run`, so you can import from `node_modules`, relative paths, or `node:` builtins.

```txt
> import { z } from "zod"
undefined
> const path = require("path")
undefined
> z.string().parse(path.join("/tmp", "file.txt"))
'/tmp/file.txt'
❯ import { join } from "node:path"
[Function: join]
❯ const basename = require("node:path").basename
[Function: basename]
❯ basename(join("/tmp", "file.txt"))
"file.txt"
```

Declarations persist for the rest of the session. Unlike in regular scripts, you can redeclare `const`/`let` across evaluations, so you can re-run `import` and `require` statements while iterating.
Expand All @@ -91,18 +98,18 @@ Declarations persist for the rest of the session. Unlike in regular scripts, you

## Multi-line input

When you press `Enter` on a line with unclosed brackets, braces, or parentheses, the REPL automatically continues on the next line. The prompt changes to `...` to indicate continuation.
When you press `Enter` on a line with unclosed brackets, braces, parentheses, or quotes, the REPL automatically continues on the next line. The prompt changes to `...` to indicate continuation.

```txt
> function add(a, b) {
❯ function add(a, b) {
... return a + b;
... }
undefined
> add(2, 3)
❯ add(2, 3)
5
```

For longer multi-line entries, use `.editor` to enter editor mode, which buffers all input until you press `Ctrl+D`.
For longer multi-line entries, use `.editor` to enter editor mode, which buffers each line that you enter until you press `Ctrl+D`.

---

Expand All @@ -120,40 +127,43 @@ Type `.help` at the prompt to see all available REPL commands.
| `.save` | Save the current REPL history to a file: `.save ./session.txt` |
| `.editor` | Enter multi-line editor mode (press `Ctrl+D` to evaluate, `Ctrl+C` to cancel) |
| `.break` | Cancel the current multi-line input |
| `.history` | Print the command history |
| `.history` | Print the last 20 history entries |

`.copy` writes the text to the terminal in an OSC 52 escape sequence. A terminal that supports OSC 52 puts the text on the clipboard.

---

## Keybindings

The REPL supports Emacs-style line editing.

| Keybinding | Action |
| ------------------- | -------------------------------------------------------- |
| `Ctrl+A` | Move to start of line |
| `Ctrl+E` | Move to end of line |
| `Ctrl+B` / `Ctrl+F` | Move backward/forward one character |
| `Alt+B` / `Alt+F` | Move backward/forward one word |
| `Ctrl+U` | Delete to start of line |
| `Ctrl+K` | Delete to end of line |
| `Ctrl+W` | Delete word backward |
| `Ctrl+D` | Delete character (or exit if line is empty) |
| `Ctrl+L` | Clear screen |
| `Ctrl+T` | Swap the two characters before the cursor |
| `Up` / `Down` | Navigate history |
| `Tab` | Auto-complete |
| `Ctrl+C` | Cancel current input (press twice on empty line to exit) |
| Keybinding | Action |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `Ctrl+A` | Move to start of line |
| `Ctrl+E` | Move to end of line |
| `Ctrl+B` / `Ctrl+F` | Move backward/forward one character |
| `Alt+B` / `Alt+F` | Move backward/forward one word |
| `Ctrl+U` | Delete to start of line |
| `Ctrl+K` | Delete to end of line |
| `Ctrl+W` | Delete word backward |
| `Ctrl+D` | Delete character (or exit if the line is empty and the prompt is not `...`) |
| `Ctrl+L` | Clear screen |
| `Ctrl+T` | Swap the character before the cursor with the character at the cursor (at the end of the line, swap the last two characters) |
| `Up` / `Down` | Navigate history |
| `Tab` | Auto-complete |
| `Ctrl+C` | Cancel current input (press twice on empty line to exit) |

---

## History

The REPL automatically saves history to `~/.bun_repl_history` (up to 1000 entries) and loads it at the start of each session. Use `Up`/`Down` to navigate.
The REPL loads the history from `~/.bun_repl_history` at the start of each session. When you exit with `.exit`, `Ctrl+D`, or `Ctrl+C`, the REPL saves the most recent 1000 entries to that file. A session that ends from a signal or a `process.exit()` call does not save its history. Use `Up`/`Down` to navigate.

To export your history to a different file, use `.save`:

```txt
> .save ./my-session.txt
❯ .save ./my-session.txt
Session saved to ./my-session.txt
```

---
Expand All @@ -166,11 +176,14 @@ Use `-e` / `--eval` to evaluate a script with REPL semantics and exit. Use `-p`
bun repl -e "const x: number = 42; console.log(x)"
# 42

bun repl -p "await fetch('https://example.com').then(r => r.status)"
bun repl -p "await fetch('https://bun.com').then(r => r.status)"
# 200

bun repl -p "{ a: 1, b: 2 }"
# { a: 1, b: 2 }
# {
# a: 1,
# b: 2,
# }
```

Both flags use the same transforms as the interactive REPL, so Bun treats a bare object literal like `{ a: 1 }` as an object expression instead of a block statement. The process exits after the event loop drains (pending timers and I/O complete first). On error, the process exits with code `1`.
Both flags use the same transforms as the interactive REPL, so Bun treats a bare object literal like `{ a: 1 }` as an object expression instead of a block statement. The process exits after the event loop drains (pending timers and I/O complete first). If the script throws an error, or a promise that it awaits at the top level rejects, Bun prints the error to standard error and the process exits with code `1`.
Loading