In Ruby 4.0's IRB, which rc files run at startup, in what order, and why is an .irbrc inside a cloned repository a risk?
answer
- IRBRC env var wins first
- XDG_CONFIG_HOME/irb/irbrc, ~/.irbrc
- then ./.irbrc in the current directory
- every file found is loaded
- irb -f skips them all
basics
~20 sIRB loads every rc file it finds: the IRBRC path, the XDG config file, ~/.irbrc or ~/.config/irb/irbrc, then .irbrc in the current directory. Each is plain Ruby, so a repository's .irbrc runs arbitrary code; irb -f skips them.
solid answer
~40 sAn rc file is Ruby that IRB `load`s before the first prompt, usually to set `IRB.conf` keys such as `:SAVE_HISTORY`, `:EVAL_HISTORY`, `:PROMPT_MODE` or `:COMMAND_ALIASES`. The IRB that Ruby 4.0 bundles builds a list in order: the file named by `IRBRC`, `$XDG_CONFIG_HOME/irb/irbrc`, `~/.irbrc`, `~/.config/irb/irbrc` when `XDG_CONFIG_HOME` is unset, then `.irbrc`, `irbrc`, `_irbrc` or `$irbrc` in the **current directory** — and loads **every** one that exists. A failing file only prints a warning. Because it is ordinary Ruby, running `irb` inside a freshly cloned repository executes that repository's `.irbrc` with your permissions. `irb -f` disables rc loading entirely; reading an unfamiliar project's `.irbrc` first is the safer habit.
code
ruby · 10 lines# ~/.irbrc
IRB.conf[:SAVE_HISTORY] = 5000
IRB.conf[:EVAL_HISTORY] = 20
IRB.conf[:COMMAND_ALIASES] = {"$": :show_source, "@": :whereami, s: :show_source}
begin
require "csv"
rescue LoadError
warn "csv not in this bundle"
endgo deeper
Know that ~/.irbrc is Ruby that runs when IRB starts and is where settings like history size go.
List the lookup order, including IRBRC, XDG paths and the current directory, and explain that every existing file is loaded.
Treat a repository's .irbrc as executable code: read it before running IRB in untrusted checkouts, and know irb -f to bypass it.
Decide whether a team ships a shared project .irbrc at all, weighing onboarding convenience against running unreviewed code on every developer's machine.
## What an rc file is When IRB starts it runs one or more **rc files** ("run commands") before printing its first prompt. They are not a config format: each one is loaded with Ruby's `load`, so it can contain any Ruby code at all. Typical contents set keys in the `IRB.conf` hash: - `IRB.conf[:SAVE_HISTORY] = 5000` — input lines kept in `.irb_history` (default 1000); - `IRB.conf[:EVAL_HISTORY] = 20` — enables `__`, the history of results; - `IRB.conf[:PROMPT_MODE] = :SIMPLE` — the `>>` prompt; - `IRB.conf[:COMMAND_ALIASES]` — the command shortcuts, `$` and `@` by default; - `IRB.conf[:COMPLETOR] = :type` — the completion engine. People also define helper methods or `require` debugging libraries there. ## Where IRB looks, in order The IRB shipped with Ruby 4.0 collects candidate paths in this order and keeps those that exist: 1. the path in the **`IRBRC`** environment variable; 2. **`$XDG_CONFIG_HOME/irb/irbrc`**, if that `irb` directory exists; 3. **`~/.irbrc`**; 4. **`~/.config/irb/irbrc`**, only when `XDG_CONFIG_HOME` is unset or empty; 5. in the **current directory**: `.irbrc`, `irbrc`, `_irbrc`, `$irbrc`. Then it `load`s **each** of them in that order. That is the part older answers get wrong: earlier IRB releases stopped at the first file found, so a personal `~/.irbrc` used to hide a project one. Now a user file and a project file both run, the project's last, so its settings win where they overlap. ## Failure and escape hatches | Situation | Behaviour | |---|---| | An rc file raises `StandardError` or a `ScriptError` such as `SyntaxError` | IRB prints `Error loading RC file` with the message and carries on. | | A known `IRB.conf` key has a wrong type (e.g. `EVAL_HISTORY` not an Integer) | Startup fails IRB's config validation with a `TypeError`. | | You start `irb -f` | No rc file is loaded at all. | The same rc files are read when IRB is started for you — `binding.irb`, IRB-based framework consoles — because they all go through IRB's setup. ## Why a project .irbrc is a risk Loading the current directory's `.irbrc` is convenient for teams (shared helpers, a project prompt), but it means **opening a console runs code chosen by whoever wrote that file**: - clone an unfamiliar repository, `cd` into it, type `irb`, and its `.irbrc` executes with your user's permissions — reading `~/.ssh`, environment variables and tokens included; - nothing prompts or warns first; the file is just `load`ed; - because the file is Ruby, reviewing it is the only way to know what it does. Practical defences: - read `.irbrc` (and `irbrc`, `_irbrc`) before starting IRB in code you did not write; - use `irb -f` when you only need a clean console; - keep secrets out of shell environments used for exploring untrusted code. ## Keeping your own rc file healthy - Guard optional libraries: `begin; require "amazing_print"; rescue LoadError; end` so a missing gem under Bundler only skips a feature. - Keep it fast; it runs on every console start. - Use `IRBRC` to point CI or containers at a known file, or `-f` to run with none.
- You have both ~/.irbrc and a project .irbrc that set IRB.conf[:PROMPT_MODE] differently. Which wins?The project file. Current IRB loads every rc file it finds, user-level locations first and the current directory's `.irbrc` last, so the later assignment to `IRB.conf[:PROMPT_MODE]` overwrites the earlier one. Older IRB releases loaded only the first file found and would have used `~/.irbrc` alone.
- Your ~/.irbrc raises NameError on a typo. Does IRB refuse to start?No. IRB rescues `StandardError` and `ScriptError` from each rc file, prints `Error loading RC file` with the full message, and continues to the prompt. Only IRB's own config validation — for example `IRB.conf[:EVAL_HISTORY]` set to a non-Integer — raises `TypeError` at startup.
- How do you start IRB in an untrusted checkout without running its .irbrc?Run `irb -f`, which sets `IRB.conf[:RC]` to false so no rc file is loaded, including your own. Alternatively read the directory's `.irbrc`, `irbrc` and `_irbrc` first, or start IRB from another directory and `require_relative` what you need.
saying these in an interview costs you the question
- IRB loads only ~/.irbrc and ignores any file in the current directory.
- A project .irbrc is a data file, so opening IRB cannot execute code.
- An exception in .irbrc stops IRB from starting at all.
- When ~/.irbrc exists, a project .irbrc is never loaded.
- irb --noscript is the flag that skips rc files.