skip to content

Rbenv

rbenv puts shims on PATH and picks a Ruby from RBENV_VERSION, a .ruby-version file up the tree or a global default, with ruby-build compiling new versions. Asked as the lighter contrast to RVM.

on this pageshow

explore

questions

5

With rbenv, how do you install a new Ruby version and pin it for one project, and what does each command write to disk?

level: juniorimportance: must knowfreq 70%

answer

  1. install comes from a plugin
  2. ruby-build compiles into versions/
  3. local writes a dotfile in cwd
  4. global writes ~/.rbenv/version
  5. shell sets only RBENV_VERSION

basics

~10 s

Run rbenv install 4.0.7 (supplied by the ruby-build plugin) to build Ruby into ~/.rbenv/versions/4.0.7, then rbenv local 4.0.7 in the project to write .ruby-version; rbenv global writes the machine default to ~/.rbenv/version.

solid answer

~30 s

`rbenv install 4.0.7` comes from the **ruby-build** plugin: it compiles Ruby into `~/.rbenv/versions/4.0.7` and then runs `rbenv rehash` so the new executables get shims. To pin a project I run `rbenv local 4.0.7` in its root, which writes a `.ruby-version` file I commit. `rbenv global 4.0.7` writes the default for everything else into `~/.rbenv/version`, and `rbenv shell 4.0.7` only sets `RBENV_VERSION` for the current shell. `local` and `global` refuse versions that are not installed. `rbenv versions` lists what is installed and `rbenv version` shows what is active and which file set it.

code

bash · 8 lines
bash
rbenv install -l            # latest stable per implementation
rbenv install 4.0.7         # builds into ~/.rbenv/versions/4.0.7
cd ~/code/invoice-api
rbenv local 4.0.7           # writes ./.ruby-version
cat .ruby-version           # 4.0.7
rbenv global 3.4.7          # writes ~/.rbenv/version
rbenv version               # 4.0.7 (set by /home/dev/code/invoice-api/.ruby-version)
rbenv versions              # lists installed, * marks the active one

go deeper

for a junior

Recall the three pins and where each one writes: local to .ruby-version in the current directory, global to ~/.rbenv/version, shell to an environment variable only.

for a middle

Explain that install belongs to ruby-build, that it rehashes after a successful build, and that local and global validate the version before writing it.

for a senior

Show you make setup reproducible: commit .ruby-version, use rbenv install -s in scripts, and upgrade ruby-build when a new release has no definition yet.

for a principal

Discuss how pinning one exact patch version per repository trades upgrade effort against every developer and CI job running an identical interpreter.

## What rbenv does, and what it leaves to a plugin **rbenv** is a Ruby version manager for Unix-like systems. Its whole job is to decide which installed Ruby answers when you type `ruby`, `gem`, `irb` or `bundle`, and to make that decision per project. It does **not** compile Ruby by itself: the `rbenv install` command comes from the **ruby-build** plugin. If `rbenv install` reports that the command does not exist, that plugin is what is missing: clone ruby-build into `"$(rbenv root)"/plugins/ruby-build`. Everything rbenv owns lives under one root directory, `RBENV_ROOT`, which defaults to `~/.rbenv`: - `~/.rbenv/versions/<name>` holds each installed Ruby, one directory per version. - `~/.rbenv/shims` holds the small wrapper scripts that sit on `PATH`. - `~/.rbenv/version` is the global default version file. - `~/.rbenv/plugins` holds plugins such as ruby-build. ## Installing a Ruby with ruby-build `rbenv install 4.0.7` downloads the Ruby 4.0.7 source, builds it and installs it into `~/.rbenv/versions/4.0.7`. When the build succeeds, the command regenerates the shims (`rbenv rehash`) so the new executables are reachable at once. The build needs a working compiler toolchain and libraries such as OpenSSL; a `BUILD FAILED` message almost always points at the build environment, not at rbenv. | Command | What it does | |---|---| | `rbenv install -l` / `--list` | Lists the latest stable release of each Ruby implementation ruby-build knows | | `rbenv install -L` / `--list-all` | Lists every definition, including old ones | | `rbenv install 4.0.7` | Builds and installs that exact version | | `rbenv install 4.0` | Resolves the prefix to the newest stable 4.0.x definition, then installs it under its full name | | `rbenv install` (no argument) | Installs whatever the project's `.ruby-version` names | | `rbenv install -s 4.0.7` | `--skip-existing`: exits quietly if that version is already installed | | `rbenv install -f 4.0.7` | `--force`: rebuilds over an existing installation | Build settings travel as environment variables: `RUBY_CONFIGURE_OPTS` adds `./configure` flags and `MAKE_OPTS` adds `make` flags. `-v` (`--verbose`) streams the full build output, which is what you want when a build fails, and `-k` (`--keep`) keeps the source tree under `~/.rbenv/sources`. The list of versions comes from ruby-build's definition files, so when a brand-new Ruby release is missing you **upgrade ruby-build**, not rbenv. ## Pinning a version: local, global and shell Three commands choose a version, and they differ in **where** they record it: 1. `rbenv local 4.0.7` writes `4.0.7` into a `.ruby-version` file in the **current directory**. Commit that file; it pins the project for everyone on the team who uses rbenv. 2. `rbenv global 4.0.7` writes the version into `~/.rbenv/version`, the default for any directory without a `.ruby-version` above it. 3. `rbenv shell 4.0.7` writes nothing to disk: it sets the `RBENV_VERSION` environment variable in the current shell only. Both `rbenv local` and `rbenv global` refuse a version that is not installed: they check it with `rbenv prefix` first and fail with a "version not installed" error, so a typo never reaches the file. Run without an argument, `rbenv local` prints the configured local version and `rbenv global` prints the global one (`system` if none was ever set). `rbenv local --unset` deletes the `.ruby-version` file. The special name **`system`** means "the Ruby that is on `PATH` without rbenv", typically the operating system's own. ## Checking what is active - `rbenv versions` lists every installed version and marks the active one with an asterisk. - `rbenv version` prints the active version and **what set it**, for example `4.0.7 (set by /home/dev/app/.ruby-version)`. - `ruby -v` confirms the interpreter the shim actually launched. ## Removing a version A version is just a directory, so `rm -rf "$(rbenv prefix 3.4.7)"` removes it; ruby-build also provides `rbenv uninstall 3.4.7`, which does the same after a confirmation prompt (`-f` skips it). ## First-day mistakes - Running `sudo gem install`: under rbenv every Ruby lives in your home directory and is writable by you. A permissions error usually means the **system** Ruby is still the global default; fix it with `rbenv global`. - Expecting `rbenv install` to switch versions: it only installs. When neither a `.ruby-version` nor a global default applies, ruby-build even prints a note suggesting `rbenv global <version>` after the install. - Forgetting to commit `.ruby-version`, so teammates silently run whatever their global default is.

  • What does rbenv install do when you run it with no version argument?
    It asks `rbenv local` for the project's version, i.e. it reads the nearest `.ruby-version`, and installs that. With no `.ruby-version` found it prints the usage and exits with an error. Combined with `-s` (`--skip-existing`) this makes `rbenv install -s` an idempotent setup step: it builds the pinned Ruby once and exits quietly afterwards.
  • What gets installed by rbenv install 4.0, and does it satisfy a .ruby-version containing 4.0?
    ruby-build resolves the prefix `4.0` to the newest stable 4.0.x definition it knows, skipping previews, release candidates and `-dev`, and installs it under its full name such as `4.0.7`. rbenv itself matches `.ruby-version` names exactly, so a file saying `4.0` still fails with 'version not installed'. Write the full version into the file.
  • rbenv install 4.0.9 reports that the definition is not found; what is the fix?
    The list of installable versions is ruby-build's set of definition files, so a release newer than your ruby-build is unknown to it. Upgrade ruby-build (through the package manager or `git pull` in its plugin directory); rbenv itself does not need changing. `rbenv install -L` shows every definition the installed ruby-build has.

saying these in an interview costs you the question

  • rbenv compiles Ruby by itself, so ruby-build is never needed
  • rbenv local switches the Ruby version for the whole machine
  • rbenv global edits PATH in the shell profile to point at a Ruby
  • Permission errors on gem install under rbenv are fixed with sudo
  • rbenv install also makes the new version active automatically
open as a page

How do rbenv shims route a ruby or bundle call to the right Ruby version, and when must you run rbenv rehash?

level: middleimportance: must knowfreq 55%

basics

~10 s

rbenv puts ~/.rbenv/shims first on PATH; each shim is a small script that runs rbenv exec, which resolves the selected version and execs that version's executable. rbenv rehash regenerates shims when new executables appear.

open as a page

In what order does rbenv decide which Ruby version is active, and how do rbenv shell, local and global map onto that order?

level: middleimportance: should knowfreq 50%

basics

~20 s

rbenv takes RBENV_VERSION first (set by rbenv shell), then the nearest .ruby-version found walking up from the current directory (written by rbenv local), then ~/.rbenv/version (written by rbenv global), and otherwise uses the system Ruby.

open as a page

Why is rbenv called the lighter alternative to RVM, and how do you isolate gems per project when rbenv has no gemsets?

level: middleimportance: should knowfreq 40%

basics

~20 s

rbenv only prepends a shims directory to PATH and resolves the version on each command, without wrapping cd or loading heavy shell functions. It has no gemsets: each installed Ruby has its own gem directory, and Bundler's lockfile isolates each project.

open as a page

A project's .ruby-version pins 4.0.7 under rbenv, yet a newly opened terminal runs the system Ruby there; how do you diagnose and fix it?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Check that ~/.rbenv/shims comes first on PATH with type -a ruby; usually the rbenv init line sits in a startup file that shell never reads, or a later PATH edit wins. Then run rbenv version to spot a stray RBENV_VERSION.

open as a page