minishell is a Unix shell written in C, developed as part of the 42 curriculum.
The goal of the project is to reproduce core shell behavior: parsing user input,
expanding variables and wildcards, handling redirections and pipes, executing
programs, and keeping interactive signal behavior close to Bash.
This code was written by hand and thought through with my own head, with all its imperfections in code structure, algorithms, naming, and tradeoffs. It belongs to the moment just before AI became the inevitable standard in daily programming.
Today I alternate between deep dives and tests before allowing myself to use AI: I first make sure I understand the tool well enough to rely on it responsibly.
I also simply love coding, and I take less pleasure and satisfaction from generating code than from building it myself. Even after all the effort spent learning these tools before using them, I still sometimes feel a little less legitimate when AI is involved.
I am still proud of this project and grateful to have it as a vestige proving my ability to think like a software engineer. It is a project where I pushed myself far beyond my comfort zone and proved to myself that I was capable.
Building a shell requires more than launching processes. This project touches low-level Unix concepts that are central to systems programming:
- process creation with
fork,execve,waitpid - pipe orchestration and file descriptor lifecycle management
- input parsing, tokenization, syntax validation, and command tree construction
- environment management and variable expansion
- terminal behavior, signals, and interactive readline handling
- memory ownership across linked lists, command structures, and execution paths
- Interactive prompt with command history through GNU Readline
- External command execution using the
PATHenvironment - Builtins:
cdechoenvexitexportpwdunset
- Pipelines with
| - Input, output, append, and heredoc redirections:
<>>><<
- Environment variable expansion, including
$? - Quote handling for single and double quotes
- Wildcard expansion with
* - Conditional execution with
&&and|| - Subshell execution with parentheses
- Signal handling for interactive usage, especially
Ctrl-C,Ctrl-\, and EOF
The code is split into focused modules:
src/
|-- built_in/ # Shell builtins
|-- data/ # Global shell state, environment, cleanup
|-- exec/ # Command execution, pipes, redirections
|-- expand/ # Variables, wildcards, heredoc expansion
|-- parsing/ # Command and redirection parsing
|-- signal/ # Interactive signal behavior
|-- token/ # Tokenization and syntax checks
|-- tree/ # Execution tree for logical operators and subshells
`-- utils/ # Shared helpers
Execution flow:
readline
-> tokenization
-> expansion
-> syntax and command parsing
-> execution tree
-> fork/exec, builtins, pipes, redirections
-> cleanup and next prompt
ccorclangmake- GNU Readline
On macOS, GNU Readline can be installed with Homebrew:
brew install readlineThe Makefile currently links Readline from /usr/local/include and
/usr/local/lib. If your installation is under /opt/homebrew, update the
Readline include and library paths in the Makefile.
make./minishellmake clean
make fclean
make reminishell$ echo hello world
hello world
minishell$ export NAME=Moha
minishell$ echo "Hello $NAME"
Hello Moha
minishell$ ls -la | grep minishell
minishell$ cat << EOF > out.txt
hello from heredoc
EOF
minishell$ false || echo "fallback"
fallback
minishell$ (cd /tmp && pwd)
/tmp- Custom lexer/parser that separates token processing from command execution
- Binary tree representation for logical operators and subshell groups
- Builtins executed in the parent process when they need to mutate shell state
- Dedicated expansion layer for variables, quotes, heredocs, and wildcards
- Centralized cleanup routines to reduce leaks across error paths
- Signal behavior adapted for parent shell, child processes, and heredoc input
This project follows the 42 school constraints:
- implemented in C
- custom
libftused for common utility functions - no use of high-level shell execution wrappers
- careful memory management and explicit resource cleanup
The main shell behavior is implemented. The project is intended as a systems programming exercise and a portfolio piece demonstrating Unix process control, parsing, and terminal programming in C.