A POSIX-compliant shell implementation written in Rust, built as part of the CodeCrafters Shell Challenge. This shell provides a command-line interface with support for built-in commands, external program execution, pipelines, I/O redirection, and interactive features.
This project is a fully functional command-line shell implementation built from scratch in Rust. It demonstrates core systems programming concepts including process management, file descriptor manipulation, signal handling, and interactive terminal control.
Building a shell from the ground up provides deep insights into:
- Process Management - How operating systems spawn and manage processes
- I/O Redirection - Understanding file descriptors, pipes, and streams
- Command Parsing - Tokenization, pipeline detection, and argument handling
- Interactive Interfaces - Terminal control, history, and autocompletion
- System Integration - PATH resolution, environment variables, and working directory management
- Modular Design - Clean separation of concerns with dedicated modules for parsing, execution, and utilities
- Type Safety - Leverages Rust's type system for safe memory management and error handling
- Interactive Experience - Rich command-line editing with tab completion and history navigation
- POSIX Compliance - Follows standard shell behavior for compatibility with existing tools
POSIX (Portable Operating System Interface) is a family of standards that define how Unix-like operating systems should behave. A POSIX-compliant shell means:
- Standard Command Syntax - Commands follow the same syntax and behavior as standard Unix shells (bash, sh, zsh)
- Compatible Behavior - Works with existing Unix/Linux tools and scripts
- Standard Features - Implements core shell features like:
- Command pipelines (
|) - I/O redirection (
>,>>,<,2>,2>>) - Built-in commands (
cd,pwd,echo, etc.) - Environment variable handling
- PATH resolution for executables
- Command pipelines (
This shell implements POSIX-compliant features, meaning scripts and commands written for standard Unix shells will work similarly here.
cd- Change directory with support for absolute/relative paths and~(home directory)pwd- Print current working directoryecho- Print arguments to stdouttype- Check if a command is a builtin or external executableexit- Exit the shell (with optional history saving viaHISTFILE)history- Display command history with support for:history- Show all historyhistory <n>- Show last n commandshistory -r <file>- Load history from filehistory -w <file>- Write history to filehistory -a <file>- Append history to file
- Command Pipelines - Chain multiple commands using
|operator - I/O Redirection - Support for
>,>>,<,2>,2>> - Tab Completion - Autocomplete for:
- Built-in commands (
echo,exit, etc.) - External executables in PATH
- Multiple matches handling (bell on first TAB, list on second TAB)
- Built-in commands (
- Command History - Navigate previous commands with arrow keys
- PATH Resolution - Execute external programs from PATH directories
- History Persistence - Automatic history loading/saving via
HISTFILEenvironment variable
- Rust 1.91 or later
- Cargo (Rust package manager)
cargo build --release./your_program.shOr directly:
cargo run$ pwd
/home/user/projects
$ echo "Hello, World!"
Hello, World!
$ cd ~/Documents
$ pwd
/home/user/Documents$ cat file.txt | wc -l
42
$ echo "hello" | tr '[:lower:]' '[:upper:]'
HELLO$ echo "Hello" > output.txt
$ cat output.txt
Hello
$ echo "World" >> output.txt
$ cat output.txt
Hello
World
$ wc -l < input.txt
10$ history
1 echo hello
2 pwd
3 history
$ history -r ~/.shell_history
$ history -w ~/.shell_history$ ec<TAB> # Completes to "echo "
$ /usr/bin/ls<TAB><TAB> # Shows all matches starting with "ls"src/
├── main.rs # Entry point and main REPL loop
└── shell/
├── mod.rs # Module declarations
├── builtin.rs # Built-in command handlers
├── completer.rs # Tab completion logic
├── constants.rs # Shell constants
├── external.rs # External command execution
├── io_utils.rs # I/O utilities and ShellReader
├── parser.rs # Command and pipeline parsing
├── path.rs # PATH resolution utilities
├── pipeline.rs # Pipeline execution logic
├── redirection.rs # I/O redirection handling
└── utils.rs # Utility functions
- Rust - Systems programming language
- rustyline - Rich command-line editing with history and completion
- shlex - Shell-like tokenization for command parsing
- libc - Low-level system calls
The shell follows a modular architecture:
- Input Layer (
io_utils.rs) - Handles user input viarustylinewith history and completion - Parser Layer (
parser.rs) - Parses commands, pipelines, and redirections - Execution Layer:
builtin.rs- Executes built-in commandsexternal.rs- Executes external programspipeline.rs- Handles command pipelines
- Utilities:
path.rs- Resolves executables in PATHredirection.rs- Manages I/O redirectioncompleter.rs- Provides tab completion
This project is part of the CodeCrafters Shell Challenge. Tests are run automatically when you push to the repository.
This project is part of the CodeCrafters educational challenge series.
- Built as part of the CodeCrafters Shell Challenge
- Inspired by POSIX shell specifications