A POSIX-like shell built from scratch in Go as part of the CodeCrafters "Build Your Own Shell" Challenge. This project implements a functional shell with a REPL, builtin commands, PATH resolution, and external program execution.
| Command | Description |
|---|---|
exit |
Exits the shell with a clean return |
echo |
Outputs arguments to stdout, preserving spacing |
type |
Identifies if a command is a shell builtin or locates it in PATH |
- REPL (Read-Eval-Print Loop): Continuous shell prompt that reads user input, processes commands, and displays output
- Invalid Command Handling: Gracefully handles unknown commands with appropriate error messages
- PATH Resolution: Searches directories in
$PATHto locate executable files - External Program Execution: Runs any executable found in PATH with full argument passing and I/O handling
┌─────────────────────────────────────────────────────────────┐
│ Shell REPL Loop │
│ ($ prompt, input) │
├─────────────────────────────────────────────────────────────┤
│ Command Parser │
│ (tokenizes input into cmd + args) │
├──────────────────────┬──────────────────────────────────────┤
│ Builtin Commands │ External Programs │
│ (exit, echo, type) │ (PATH lookup + exec.Command) │
└──────────────────────┴──────────────────────────────────────┘
- Input Handling: Buffered reader with proper EOF and error handling
- Command Parsing: Splits input into command and arguments using
strings.Fields - Builtin Registry: Map-based lookup for O(1) builtin command identification
- PATH Search: Iterates through PATH directories, checking file existence and executable permissions
- Process Execution: Uses Go's
os/execpackage with stdin/stdout/stderr passthrough
func findExecutable(cmd string) (string, bool) {
// 1. Get PATH environment variable
// 2. Split into directories by OS path separator
// 3. For each directory, check if cmd exists and is executable
// 4. Return full path if found, empty string otherwise
}The executable check verifies the file's mode bits (mode&0111 != 0) to ensure it has execute permissions.
- Print a prompt - Display
$and wait for input - Handle invalid commands - Return
<cmd>: command not found - Implement a REPL - Continuous command loop
- Implement exit - Clean shell termination
- Implement echo - Output arguments to stdout
- Implement type - Identify builtin commands
- Locate executable files - Search PATH for executables
- Run a program - Execute external programs with arguments
# Start the shell
./your_program.sh
# Or run directly with Go
go run app/main.go$ echo Hello World
Hello World
$ type echo
echo is a shell builtin
$ type cat
cat is /bin/cat
$ type nonexistent
nonexistent: not found
$ cat README.md
# (displays file contents)
$ exit.
├── app/
│ └── main.go # Complete shell implementation
├── your_program.sh # Shell startup script
└── README.md
- Systems Programming: Building a shell that interfaces directly with the operating system
- Process Management: Spawning and managing child processes with proper I/O handling
- Environment Variables: Parsing and utilizing PATH for executable resolution
- Input Parsing: Tokenizing user input into commands and arguments
- Error Handling: Graceful handling of invalid commands, missing files, and execution errors
Built as part of the CodeCrafters challenge series.