https://github.com/oilshell/oil/
And a blog here: http://www.oilshell.org/ (index: http://www.oilshell.org/blog/2016/11/20.html)
This article is good in that it shows that starting processes boils down to the system calls fork(), exec(), wait(), etc.
My shell has function calls, loops, conditionals, pipelines, subshells, command substitution, redirects, here docs, etc. (The code has some messiness, but the architecture is clean IMO.)
It turns out that these features require just a few more system calls -- dup2() and fcntl() to manipulate file descriptors, pipe(), and open() / read() / write() / close(). It's a good reminder of how simple Unix is. The complexity of the shell is basically all in string processing, and not in interfacing with the kernel (although the interactive parts of the shell do complicate things).
These system calls are all available in Python, so the code ends up being comparable to what you would write in C (and I'm in the process of porting to C++ now that the architecture has settled.)