LmCast :: Stay tuned in

Rubish: A Unix shell written in pure Ruby

Recorded: May 23, 2026, 9:58 a.m.

Original Summarized

GitHub - amatsuda/rubish · GitHub

Skip to content

Navigation Menu

Toggle navigation

Sign in

Appearance settings

PlatformAI CODE CREATIONGitHub CopilotWrite better code with AIGitHub SparkBuild and deploy intelligent appsGitHub ModelsManage and compare promptsMCP RegistryNewIntegrate external toolsDEVELOPER WORKFLOWSActionsAutomate any workflowCodespacesInstant dev environmentsIssuesPlan and track workCode ReviewManage code changesAPPLICATION SECURITYGitHub Advanced SecurityFind and fix vulnerabilitiesCode securitySecure your code as you buildSecret protectionStop leaks before they startEXPLOREWhy GitHubDocumentationBlogChangelogMarketplaceView all featuresSolutionsBY COMPANY SIZEEnterprisesSmall and medium teamsStartupsNonprofitsBY USE CASEApp ModernizationDevSecOpsDevOpsCI/CDView all use casesBY INDUSTRYHealthcareFinancial servicesManufacturingGovernmentView all industriesView all solutionsResourcesEXPLORE BY TOPICAISoftware DevelopmentDevOpsSecurityView all topicsEXPLORE BY TYPECustomer storiesEvents & webinarsEbooks & reportsBusiness insightsGitHub SkillsSUPPORT & SERVICESDocumentationCustomer supportCommunity forumTrust centerPartnersView all resourcesOpen SourceCOMMUNITYGitHub SponsorsFund open source developersPROGRAMSSecurity LabMaintainer CommunityAcceleratorGitHub StarsArchive ProgramREPOSITORIESTopicsTrendingCollectionsEnterpriseENTERPRISE SOLUTIONSEnterprise platformAI-powered developer platformAVAILABLE ADD-ONSGitHub Advanced SecurityEnterprise-grade security featuresCopilot for BusinessEnterprise-grade AI featuresPremium SupportEnterprise-grade 24/7 supportPricing

Search or jump to...

Search code, repositories, users, issues, pull requests...

Search

Clear

Search syntax tips

Provide feedback


We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.
You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

amatsuda

/

rubish

Public

Notifications
You must be signed in to change notification settings

Fork
2

Star
81

Code

Issues
0

Pull requests
0

Actions

Projects

Security and quality
0

Insights

Additional navigation options

Code

Issues

Pull requests

Actions

Projects

Security and quality

Insights


amatsuda/rubish

 masterBranchesTagsGo to fileCodeOpen more actions menuFolders and filesNameNameLast commit messageLast commit dateLatest commit History544 Commits544 Commits.github/workflows.github/workflows  binbin  exeexe  liblib  sigsig  testtest  .dockerignore.dockerignore  .gitignore.gitignore  DockerfileDockerfile  GemfileGemfile  LICENSE.txtLICENSE.txt  README.mdREADME.md  RakefileRakefile  rubish-gem.gemspecrubish-gem.gemspec  View all filesRepository files navigationREADMEMIT licenseRubish
A UNIX shell written in pure Ruby.
Shell syntax is parsed and compiled to Ruby code, then executed by the Ruby VM.
Concept
Fully Bash-compatible
Rubish supports all the features of bash, and the shell syntax is fully compatible. You can run your existing bash scripts without modification. If you found any bash script that doesn't work in rubish, we consider it a bug, so please report it!
Deep Ruby integration
Rubish is not just a shell implemented in Ruby, but a shell that deeply integrates Ruby. You can seamlessly mix shell commands and Ruby code, and even use Ruby's powerful features like blocks, iterators, and libraries in your shell scripts.
Installation
Homebrew (macOS)
brew tap amatsuda/rubish
brew install --HEAD rubish

From source
git clone https://github.com/amatsuda/rubish.git
cd rubish
bundle install
bundle exec exe/rubish
bin/rubish is a small bash launcher that finds a usable Ruby on its own (probes ~/.rbenv/shims/ruby, /opt/homebrew/bin/ruby, /usr/local/bin/ruby, system Ruby; honors $RUBY). Use it when bundler isn't around — for example as a login shell, from a .app bundle, or anywhere PATH may be minimal:
./bin/rubish
RUBY=/opt/homebrew/opt/ruby@3.4/bin/ruby ./bin/rubish # explicit override
Usage
Start an interactive shell:
rubish
Run a single command:
rubish -c 'echo hello'
Run a script:
rubish script.sh
Or you can even use this as a login shell!
Set as login shell
echo "$(which rubish)" | sudo tee -a /etc/shells
chsh -s "$(which rubish)"
Features beyond Bash
Ruby conditions
Use Ruby expressions as conditions in if, while, and until by wrapping them in { }. Shell variables are automatically bound as local variables in the Ruby expression:
COUNT=5
if { count.to_i > 3 }
echo 'count is greater than 3'
end

while { count.to_i > 0 }
echo $COUNT
COUNT=$((COUNT - 1))
done
Ruby method call style
Commands can be invoked using Ruby method call syntax with parentheses, in addition to the traditional UNIX style with spaces:
# These are equivalent:
ls -la
ls('-la')

# Arguments can be passed as method arguments:
cat(file.txt)
grep('pattern', file.txt)
Method chaining
Commands can be chained with Ruby methods using dot notation, forming a pipeline. The chain has to be opened by a parenthesized call, an array literal, or a block — once you're in chain context, subsequent methods can be bare:
# Equivalent to `ls | sort`
ls().sort

# Equivalent to `ls | sort | uniq`
ls().sort.uniq

# Equivalent to `cat file.txt | grep error`
cat(file.txt).grep(/error/)

# Chains can be combined with blocks (see "Ruby iterator blocks" below)
ls.select { it.end_with?('.rb') }.each { |f| puts f.upcase }
The first segment needs the parens because bare cmd.method is ambiguous with paths and dotted filenames (./script.sh, file.tar.gz) — once () confirms a method-call form, the lexer knows it's safe to chain.
Ruby iterator blocks
Ruby iterator methods (.each, .map, .select, .detect) can take blocks to process command output line by line:
ls.each { |f| puts f.upcase }
cat(file.txt).map { |line| line.strip }
ls.select { it.end_with?('.rb') }
Inline Ruby evaluation
Any line starting with a capital letter is evaluated as Ruby code directly. This means you can use Ruby classes, methods, and expressions right from the shell prompt without any special syntax:
rubish$ Time.now
=> 2025-01-01 12:00:00 +0900

rubish$ Dir.glob('*.rb').sort
=> ["Gemfile", "Rakefile"]

rubish$ ENV['HOME']
=> "/Users/you"

Ruby array and regexp literals
Ruby array literals can be used directly in shell context. Rubish distinguishes them from glob patterns like [a-z] automatically:
rubish$ [1, 2, 3].map { |x| x * x }
=> [1, 4, 9]

Lambda expressions
You can execute any Ruby code by surrounding it with a lambda expression (-> { }):
rubish$ -> { 2 ** 10 }
=> 1024

Ruby-style function definitions
In addition to the standard shell function syntax, rubish supports Ruby-style def...end with named parameters and splat args:
def greet(name)
echo "Hello, $name"
end

def log(level, *messages)
echo "[$level] $messages"
end

greet world # => Hello, world
Custom Ruby prompts
Define your prompt as a Ruby function for full programmatic control. The function is called on every prompt render, so it can include dynamic content:
def rubish_prompt
branch = `git branch --show-current 2>/dev/null`.strip
dir = Dir.pwd.sub(ENV['HOME'], '~')
"\e[36m#{dir}\e[0m \e[33m#{branch}\e[0m $ "
end

def rubish_right_prompt
Time.now.strftime('%H:%M:%S')
end
You can also use the traditional PS1/RPROMPT variables with bash (\X) or zsh (%X) escape codes.
Lazy loading
Slow shell initializations (e.g., rbenv init, nvm, pyenv) can be deferred to a background thread using lazy_load. The block runs immediately in the background, and its result (a string of shell code) is applied before the next prompt. This keeps shell startup instant:
# In ~/.rubishrc
lazy_load {
`rbenv init - --no-rehash bash`
}

lazy_load {
`nodenv init - bash`
}
Multiple lazy_load blocks run in parallel. By the time you type your first command, they're usually done.
Restricted mode
Running rubish -r disables all Ruby integration features (inline evaluation, lambdas, blocks, Ruby conditions, and array literals) for executing untrusted scripts safely. Only standard shell syntax is allowed.
Zsh compatibility
In addition to full Bash compatibility, rubish also supports zsh-style features:

setopt/unsetopt
compdef/compinit
autoload with fpath
%X prompt codes and RPROMPT/RPS1
Abbreviated path expansion: type a/c/a<Tab> and it expands to app/controllers/application_controller.rb

Configuration files
Login shells load (in order):

/etc/profile
~/.config/rubish/profile or ~/.rubish_profile (or ~/.bash_profile / ~/.bash_login / ~/.profile)

Interactive shells load:

~/.config/rubish/config or ~/.rubishrc (or ~/.bashrc)
./.rubishrc (project-local)

Logout:

~/.config/rubish/logout or ~/.rubish_logout (or ~/.bash_logout)

Embedding in a Ruby program
Rubish exposes a public API so other Ruby programs (terminal emulators, IDE plugins, GUI front-ends) can drive a rubish session in-process — no fork+exec, no JSON serialization, just method calls. The sibling Echoes terminal emulator uses this to render syntax-highlighted prompts and decide command-execution shape ahead of time.
require 'rubish'

repl = Rubish::REPL.new(login_shell: true)

# Run interactively (default).
repl.run

# Or drive it programmatically.
repl.tokenize('ls | grep foo') # => Array of Rubish::Lexer::Token (each
# with :type and :value) for syntax
# highlighting; never raises.
repl.try_parse('if true; then') # => :ok | :incomplete | :error
# (use to decide PS2 vs. submit).
repl.parse_ast('echo hi') # => AST root, or nil on parse failure.
repl.complete_at(line: 'gi', point: 2) # => Array of completion candidates at
# the cursor.
repl.prompt_segments # => Array of styled-text segments
# {text:, fg:, bg:, bold:, italic:,
# underline:, inverse:}, ANSI codes
# already parsed.
repl.right_prompt_segments # => same shape for the right prompt,
# or nil if unset.
Custom I/O backend
The default Rubish::Frontend::Tty wraps Reline + stdin/stdout. Hosts that own their own line editor can subclass Rubish::Frontend::Base and pass an instance into the REPL:
class MyFrontend < Rubish::Frontend::Base
def read_line(prompt:, rprompt: nil)
# ...feed input from your own UI here
end
end

Rubish::REPL.new(frontend: MyFrontend.new).run
Child-process pre-exec hook
To run setup code in every forked child between fork() and exec() (e.g. to attach a per-command controlling tty so the line discipline can deliver Ctrl-C to the child):
Rubish::Command.child_pre_exec_hook = -> {
Process.setsid
# ...ioctls, signal handlers, etc.
}
Builtins

Category
Commands

Directory
cd, pwd, pushd, popd, dirs

I/O
echo, printf, read, mapfile, readarray

Variables
export, declare, typeset, readonly, unset, local, shift, set

Process
exit, logout, exec, kill, wait, times

Job control
jobs, fg, bg, disown, suspend

Functions
function, return, caller

Aliases
alias, unalias

History
history, fc

Execution
eval, source, ., command, builtin

Testing
test, [, [[, (( )), let

Control
break, continue, trap

Completion
complete, compgen, compopt, bind

Config
shopt, setopt, unsetopt

Info
help, type, which, hash

Other
true, false, :, getopts, umask, ulimit, enable

Development
bundle install
bundle exec rake test
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/amatsuda/rubish.
License
MIT

About

No description, website, or topics provided.

Resources

Readme

License

MIT license

Uh oh!

There was an error while loading. Please reload this page.


Activity
Stars

81
stars
Watchers

1
watching
Forks

2
forks

Report repository

Releases

1
tags

Packages
0

 

 

 

Uh oh!

There was an error while loading. Please reload this page.


Contributors

Uh oh!

There was an error while loading. Please reload this page.


Languages

Ruby
99.8%

Other
0.2%

Footer

© 2026 GitHub, Inc.

Footer navigation

Terms

Privacy

Security

Status

Community

Docs

Contact

Manage cookies

Do not share my personal information

You can’t perform that action at this time.

Rubish is presented as a UNIX shell implemented in pure Ruby, distinguished by its deep integration of Ruby programming concepts with traditional shell functionality. The core design ensures that Rubish maintains full compatibility with Bash, allowing users to execute existing Bash scripts without modification. This compatibility is achieved by parsing and compiling shell syntax into executable Ruby code, which is then run by the Ruby Virtual Machine. The primary distinction of Rubish lies in its ability to seamlessly mix shell commands with powerful Ruby features such as blocks, iterators, and libraries directly within shell scripts and interactive sessions.

Installation methods include using Homebrew on macOS, which provides commands to tap the repository and install the package, or cloning the source code from the repository and running bundle install. The executable, bin/rubish, functions as a small Bash launcher designed to locate a suitable Ruby installation, respecting the $RUBY environment variable. Users can interact with the shell in several ways, including starting an interactive session, executing a single command, or running a script, and it can also be configured as a login shell.

Beyond basic command execution, Rubish incorporates advanced Ruby features directly into shell scripting. For conditional logic, Ruby expressions can be used within if, while, and until statements, where shell variables are automatically bound as local variables within these expressions. Furthermore, command invocation supports Ruby method call syntax, allowing commands to be invoked using parentheses, such as ls('-la'), and arguments can be passed as method arguments, such as cat(file.txt). This capability extends to establishing pipelines through method chaining using dot notation, provided the chain is initiated by a parenthesized call, an array literal, or a block, which serves to disambiguate method calls versus file paths.

The system supports complex data processing via Ruby iterator blocks, such as .each, .map, and .select, which can be applied to command output line by line, enabling sophisticated filtering and transformation. Inline Ruby evaluation allows any line starting with a capital letter to be executed as Ruby code directly from the shell prompt, enabling dynamic computations using Ruby classes and methods. The system also supports Ruby array and regular expression literals, and the use of lambda expressions for defining executable blocks. The shell also supports defining custom functions using Ruby-style def...end syntax, including named parameters and splat arguments.

The architecture allows for highly customizable user experiences through the definition of custom Ruby prompts, which can dynamically incorporate information gathered from the environment or Git status at the prompt rendering time. Performance optimization is addressed through lazy loading, a mechanism that defers the execution of slow shell initializations, such as those related to environment setup, to a background thread, ensuring instant shell startup. The system also offers a restricted mode, executed via rubish -r, which disables all advanced Ruby integrations, confining execution strictly to standard shell syntax for enhanced security when handling untrusted scripts. Compatibility extends to Zsh features and prompt codes, in addition to full Bash support.

The integration extends into the programmatic layer via a public API, allowing other Ruby programs to interact with a Rubish session in-process without relying on separate processes or serialization. This API enables functionalities such as tokenizing command input, parsing Abstract Syntax Trees (ASTs), performing completion suggestions, and managing prompt segments with color and styling. Furthermore, the system offers options for custom I/O backends to integrate with external front-end processes. Built-in commands cover essential system operations including directory manipulation, input/output functions, variable management, process control, history management, and execution control.