This project is a custom implementation of a POSIX-compliant shell built in Java. It interprets shell commands, runs external programs, and supports built-in commands like cd, pwd, echo, and more. The shell also includes features like command parsing, redirection, and autocompletion.
This project is part of the “Build Your Own Shell” Challenge by Codecrafters. It is a great way to learn about how shells work internally and practice advanced Java programming concepts.
📑 Table of Contents
📌 What This Project Does
This project implements a shell that:
- Accepts user input to execute commands.
- Supports built-in commands like
cd,pwd,echo, andexit. - Runs external programs by searching for executables in the system’s
PATH. - Handles input/output redirection (e.g.,
>,>>,2>). - Provides autocompletion for commands and executables.
The purpose of this project is to understand how shells work and practice building a complex system from scratch.
⚙️ How to Set Up and Run
Prerequisites
- Java 23: Ensure you have Java 23 installed.
- Maven: Install Maven for building the project.
- Linux Environment: The shell uses POSIX features, so it works best on Linux.
Installation
-
Clone the repository:
git clone https://github.com/Md-Talim/codecrafters-shell-java.git cd codecrafters-shell-java -
Build the project using Maven:
mvn clean package -
Run the shell:
./your_program.sh
Usage
- You’ll see a prompt like
$. - Enter commands like
pwd,echo Hello, orls. - Use
Ctrl+Dorexitcommand to exit the shell.
✨ Key Features
-
Built-in commands: Supports common commands like:
cd: Change directorypwd: Print working directoryecho: Print textexit: Exit the shelltype: Show whether a command is built-in or external
-
External command support: If a command isn’t built-in, the shell searches the system
PATHand runs it using Java’sProcessBuilder. -
I/O redirection: Redirect output and errors using:
>(overwrite)>>(append)2>(redirect stderr)
-
Autocompletion: Press
Tabto auto-complete command names or see suggestions. -
Error handling
- Displays clear error messages when commands fail or are used incorrectly
- Handles missing files, bad arguments, and permission issues gracefully
- Prevents the shell from crashing due to unexpected input or runtime errors
-
Raw terminal mode: Switches the terminal to raw mode to capture user input character by character—enabling advanced input behavior like autocompletion.
🔍 How It Works Internally
Here’s a simplified look at how the shell is structured under the hood:
| Component | Role |
|---|---|
Shell.java | The main loop that reads input, parses commands, and executes them. |
Parser.java | Breaks the input line into tokens, handles redirection and quoting. |
CommandRegistry | Registers and manages built-in commands. |
ExternalCommand.java | Executes non-built-in programs via ProcessBuilder. |
Redirection.java | Handles output and error redirection to files. |
AutoCompleter.java | Provides suggestions for commands using Tab. |
Termios.java | Enables raw terminal mode via JNA to control low-level terminal settings. |
🧰 Technologies Used
- Java: The primary programming language.
- Maven: For building and managing dependencies.
- JNA (Java Native Access): For interacting with low-level terminal settings.
- POSIX: For shell behavior and command execution.
📁 Folder and File Structure
src/
main/
java/
Main.java # Entry point of the program
shell/
Shell.java # Core shell logic
command/ # Built-in commands
environment/ # Environment management
io/ # Input/output utilities
parser/ # Command parsing
process/ # External command execution
terminal/ # Terminal control
autocomplete/ # Autocompletion logic
Key files:
Main.java: Starts the shell and handles user input.Shell.java: Manages commands and execution.Parser.java: Parses user input into commands and arguments.SystemProcessExecutor.java: Executes external commands.
💡 Challenges & Lessons Learned
Challenges
-
Command Parsing:
- Handling quotes, escape characters, and redirection operators was tricky.
-
Redirection:
- Managing file output and error streams required careful design.
-
Autocompletion:
- Implementing a responsive and accurate autocompletion system was challenging.
-
Terminal Control:
- Disabling echo and enabling raw mode required low-level terminal manipulation.
Lessons Learned
- Gained a deep understanding of how shells work.
- Improved skills in Java, especially working with
ProcessBuilderand file I/O. - Learned about terminal control using JNA and POSIX standards.
🛠️ Why I Built This Project
I built this project to:
- Practice advanced Java programming concepts.
- Learn how Bash/Zsh-like shells work under the hood
- Practice writing clean, modular, and testable Java code
- Solve a real-world systems-level problem from scratch
This project helped me grow as a backend/systems engineer and is one of my favorite learning experiences.