A lightweight, POSIX-style shell written in Java
Built to explore how Unix shells work — from parsing and tokenization to process execution and redirection.
BShell is a minimal but fully interactive command-line shell implemented in Java. It supports external program execution, pipelines, built-in commands, output redirection, full quoting and escaping, command history with persistence, and tab completion — all with a clean, modular codebase designed for learning and extension.
Whether you're curious how shells parse commands, spawn processes, or handle I/O redirection, BShell offers a readable reference implementation without the complexity of bash or zsh.
| Category | Capabilities |
|---|---|
| Built-ins | cd, pwd, echo, type, exit |
| History | history, history -w, history -a, history -r with file persistence |
| Execution | Run any program on your PATH |
| Pipelines | Chain commands with | (e.g. ls | grep foo) |
| Redirection | >, >>, 2>, 2>> for stdout and stderr |
| Quoting | Full support for single quotes, double quotes, and escaping |
| Interactivity | Readline-style editing, history navigation, tab completion (built-ins + PATH commands) |
| Parsing | Tokenization and command structure parsing |
Prerequisites: Java 23+ (or adjust pom.xml), Maven
# Clone and enter the project
git clone https://github.com/<your-username>/codecrafters-shell-java.git
cd codecrafters-shell-java
# Build
mvn clean package
# Run BShell
./bshell.shOr run via Maven:
mvn exec:java -Dexec.mainClass="Main"Once BShell is running, use it like a typical Unix shell:
External commands
ls -la
grep "pattern" file.txt
cat /etc/os-releaseBuilt-in commands
cd /tmp
pwd
echo "Hello from BShell"
type cd # shows whether cd is built-in or external
exitHistory (with file persistence)
history # show command history
history -w # write history to file
history -a # append new entries to history file
history -r # reload history from filePipelines
ls -la | grep ".txt"
cat file.txt | wc -l
ps aux | head -5Output redirection
echo "log line" > out.log
echo "another line" >> out.log
ls missing-file 2> errors.log
ls missing-file 2>> errors.logQuoting and escaping
echo 'single quoted $var stays literal'
echo "double quoted $HOME expands"
echo "escape \"quotes\" and newlines\n"src/main/java/
├── Main.java # Entry point
├── commandexecution/
│ ├── BShell.java # Main REPL loop, orchestration
│ ├── CommandExecutor.java # Process spawn & I/O wiring
│ ├── CommandRunner.java # Execution orchestration
│ ├── Command.java # Parsed command representation
│ ├── RedirectHandler.java # Redirection setup
│ ├── parser/ # Tokenizer, Parser
│ ├── redirect/ # >, >>, 2>, 2>> implementations
│ ├── autocompletion/ # Tab completion (builtins + PATH)
│ └── lineinputhandler/ # JLine-based input handling
├── builtincommands/ # cd, echo, pwd, type, exit, history variants
├── history/ # HistoryManager, HistoryStorage
└── exception/ # Shell-specific exceptions
Design principles
- Separation of concerns — Parsing, execution, built-ins, redirection, and history live in dedicated packages.
- Extensibility — Add built-ins by implementing
BuiltInCommandand registering them inCommandRegistry.
Build JAR with dependencies
mvn clean package
# Produces target/codecrafters-shell.jar (or via assembly in /tmp)Debugging — Add logging in BShell or CommandExecutor to trace command parsing and execution.
Current limitations
- No command chaining (
&&,||,;) - No background jobs (
&), job control (fg,bg) - No shell variables, conditionals, loops, or functions
Possible next steps
- Command chaining (
&&,||,;) - Configurable history file location and size
- Additional built-ins (
which,alias,unalias,set)
Contributions, ideas, and bug reports are welcome.
Reporting issues — Please include:
- The exact command you ran
- What BShell did
- What you expected (e.g., compared to bash)
Pull requests — Keep changes focused.
MIT License — see LICENSE for details.