# rbenv picks the Ruby version for you by rewriting PATH

> The MIT-licensed bash project behind a lot of Ruby development reads a .ruby-version file in whatever directory you are in. Installing it takes one clone and one init call.

**rbenv/rbenv** — Manage your app's Ruby environment

- Repository: https://github.com/rbenv/rbenv
- Website: https://rbenv.org/
- Stars: 16,736 · Forks: 1,428
- Language: Shell
- License: MIT
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/rbenv-rbenv

## The mechanism is three steps, and you already know all of them

Here is the entire idea, and it is worth reading closely before installing anything. At install time, rbenv injects itself into your `PATH`. From then on, any call to `ruby`, `gem`, `bundler` or another Ruby executable hits rbenv first instead of a real Ruby.

When that happens, rbenv scans the current directory for a file named `.ruby-version`. If it finds one, that string is the version to use. It then looks up that version among the ones installed under `~/.rbenv/versions/`. If there is no `.ruby-version` anywhere up the directory tree, rbenv falls back to the global version.

So setting a version is writing a filename:

```sh
cd myproject
# choose Ruby version 3.1.2:
rbenv local 3.1.2
```

The reason to prefer this design over a project manifest is that it costs nothing to read. Walking up a directory tree looking for a small text file is fast enough to do on every single `ruby` invocation, which is the price of resolving the version without a running process. The README says almost every part of the mechanism is customizable through plugins written in bash, which is the extension point if this model is too thin for what you need.

## Installing it, and the shell profile step people skip

If you have Homebrew, the README recommends the package manager route and it is one command:

```sh
brew install rbenv
```

Official packages exist elsewhere too: `sudo pacman -S rbenv` on Arch and derivatives, `sudo dnf install rbenv` on Fedora, `sudo zypper in rbenv` on OpenSUSE Tumbleweed. The Debian and Ubuntu packages come with an explicit caution, because the version in those repositories is out of date and the git checkout is the way to get current code.

The git checkout installs into your home directory with no system-wide install at all:

```sh
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
```

Either route ends the same way. Load rbenv into your shell, then open a new terminal window:

```sh
rbenv init
```

That restart step is not ceremony. Init writes to your shell startup files, so the current window keeps the old `PATH` until it is reopened. Since v1.3.0, `rbenv init` edits those files itself instead of printing instructions meant for a human to copy, which the release notes name as the single most common pitfall. Init in setup mode also defaults to no auto-rehashing, and the generated script adds rbenv to `PATH` if it is missing.

## Ruby itself comes from a plugin

This is the part that trips up new users, and the README states it plainly: `rbenv install` does not ship with rbenv. The command is provided by the ruby-build plugin, which compiles Ruby from source.

Before your first install, check that your build environment has the libraries Ruby needs to compile. Then the commands are:

```sh
# list latest stable versions:
rbenv install -l

# list all local versions:
rbenv install -L

# install a Ruby version:
rbenv install 3.1.2
```

The distinction between the two list flags matters more than it looks. `-l` gives you the stable releases, `-L` gives the full set including older and preview builds, so a version that does not appear in `-l` may still be installable.

If the command is missing, the plugin installs the same way rbenv does:

```sh
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
```

Compiling Ruby takes minutes and fails with a `BUILD FAILED` message when a library is missing, which is what the build-failure discussions in the ruby-build repository are for. The workaround the README documents is to build manually into a subdirectory of `~/.rbenv/versions` yourself, and a symlink there counts as an installed version, which also gives you a way to point rbenv at a Ruby managed by something else.

## Global, local, and why gems need no sudo

Two commands decide which Ruby you get. `rbenv global` sets the default for the machine, and `rbenv local` writes `.ruby-version` in the current directory only:

```sh
rbenv global 3.1.2   # set the default Ruby version for this machine
# or:
rbenv local 3.1.2    # set the Ruby version for this directory
```

Once a version is active, gems install the way they always did, with no rbenv in the command:

```sh
gem install bundler
```

The README is emphatic that you should not use `sudo` here, and the reason is diagnostic. Each Ruby installs its gems under your home directory and is writable by you, so a permissions error almost always means the system Ruby is still the global default. The fix is `rbenv global <version>` rather than escalating privileges, which would scatter root-owned files into a directory your user cannot update.

`gem env home` confirms where things landed, and the README shows the shape of the answer:

```sh
gem env home
# => ~/.rbenv/versions/<version>/lib/ruby/gems/...
```

If that path says `versions/system` instead of a version number, rbenv is still deferring to the Ruby your operating system installed, and every gem you install goes somewhere you did not intend.

## Shell completions need different treatment per shell

Tab completion is a small feature that behaves differently depending on how you installed rbenv, and the README gives per-shell instructions rather than one setup.

For bash, the completion script ships with the project and the `rbenv init` mechanism loads it for you, so there is nothing to configure. For zsh, the script also ships with the project but zsh will not find it unless the completions directory is on `FPATH`:

```sh
# assuming that rbenv was installed to `~/.rbenv`
FPATH=~/.rbenv/completions:"$FPATH"

+autoload -U compinit
+compinit
+```

+Those lines go in `~/.zshrc`. The fish case is different again, because the completion script for fish ships with fish itself and rbenv does not maintain it.

The reason completion is mentioned at all in an install guide is that a missing `rbenv uninstall` or a mistyped subcommand is much easier to recover from when you can tab through the command list. Note that this split only applies to manual installs; a package manager may arrange these paths for you.

## Recent releases are mostly shell compatibility

The release history describes what kind of project rbenv is. v1.3.2 fixed PATH traversal for bash older than 4.4, and v1.3.1 switched to `readarray` on bash 4 and above specifically to avoid `rbenv init` hanging, added `/usr/etc/rbenv.d` to the hooks path, and added Fedora installation instructions. The bash version dependency in both fixes is the interesting part, since it says the priority is running on the widest range of machines rather than on the newest one.

v1.3.0 is the substantial one, and its stated theme was user-friendliness for newcomers. Beyond the `rbenv init` change and the PATH addition already mentioned, it simplified symlink resolution and removed a native bash extension, which the notes identify as a GPL license compliance issue: a GPL-licensed script was being distributed with the project, which is the sort of thing a small MIT project has to take seriously.

The repository is mostly shell. `bin/`, `libexec/`, `src/` and `test/` sit alongside `rbenv.d/`, `completions/`, `share/` and a Makefile, and that Makefile does exactly one thing worth noting: it generates the man page with `asciidoctor` from an asciidoc source, taking the version number straight from `bin/rbenv --version`. Documentation and code stay in sync because the version string is never typed by hand.

## Conclusion

rbenv's design is worth understanding as a whole rather than as a feature list, because almost every question about it resolves into the same fact: it owns your `PATH`. Once a shim sits in front of `ruby`, `gem` and `bundler`, the version in effect is decided by a text file in the current directory, and there is no daemon, no project manifest to parse and no Ruby process involved in the decision. That is why it works with any project layout and why it also means a stale shell profile or a system Ruby still on `PATH` produces confusing errors. Two boundaries are worth stating plainly. Ruby itself does not ship with rbenv, `rbenv install` arrives through the separate ruby-build plugin, and rbenv does nothing on Windows, which the README is explicit about by limiting the tool to Unix-like systems. The v1.3.0 release changed `rbenv init` to edit your shell files rather than print instructions, and the two releases after it fixed a hanging init on bash 4+ and PATH traversal on bash older than 4.4, so the rough edges people remember are being worked on. The repository is MIT licensed with 1,429 forks, 17 open issues, and a last push on 2026-07-14.

## FAQ

### How do I remove rbenv from my machine?

Removal follows the inverse of installation. If you used the git checkout, delete the `~/.rbenv` directory, then remove the line that `rbenv init` added to your shell startup file, since `~/.rbenv/bin/rbenv init` is what writes it. Close and reopen your terminal so the old PATH entries disappear. If you installed through Homebrew or your distribution's package manager, uninstall that package instead. Any Ruby you built lives under `~/.rbenv/versions` and is removed with the directory.

### Which is better, RVM or rbenv?

rbenv is a small bash script that changes your PATH and reads a `.ruby-version` file, and it keeps almost everything out of Ruby itself, which is why `ruby`, `gem` and `bundler` keep behaving normally once it is active. RVM is a larger system with more features built in, including gemsets for isolating dependencies, at the cost of a heavier install. Choose by whether you need those features or would rather keep Ruby out of rbenv's way. The README links a comparison of version managers for the details.

### What are rbenv shims?

Shims are the small executable files rbenv places ahead of the real Ruby tools in your PATH. When you run `ruby` or `gem`, the shim is what receives the call first, and it resolves the version from `.ruby-version` in the current directory or the global setting, then hands off to the matching Ruby under `~/.rbenv/versions`. Installing rbenv puts these shims in place, which is why a version change takes effect without touching any other configuration.

### How do I install rbenv on a Mac?

Homebrew is the route the README recommends on macOS, and it is one command: `brew install rbenv`. Then run `rbenv init` to add rbenv to your shell startup file, and open a new terminal window so the change takes effect. Ruby itself is a separate step because it comes from the ruby-build plugin, so run `rbenv install -l` to list stable versions and `rbenv install 3.1.2` to build one.

## Sources

- [License: MIT](https://github.com/rbenv/rbenv/blob/master/LICENSE)
- [Project website](https://rbenv.org/)
- [rbenv/rbenv on GitHub](https://github.com/rbenv/rbenv)
- [README](https://github.com/rbenv/rbenv/blob/master/README.md)
- [Releases](https://github.com/rbenv/rbenv/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/rbenv-rbenv
