HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
oils-for-unix
oils
Python2016–2025
oils-for-unix / oils

oils

Oils is our upgrade path from bash to a better language and runtime. It's also for Python and JavaScript users who avoid shell!

35Distinct people
225Mentions
1Explicit recommenders
3.4KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Oils is our upgrade path from bash to a better language and runtime. It's also for Python and JavaScript users who avoid shell!

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

There are Usenix papers on bash and ksh -- I archived the ksh one here: http://www.oilshell.org/archive/ksh-usenix.pdf The surprising thing to me is that ksh was Lua-like in…

chubot used a recommendation phrase. 4 indexed comments match. This is a phrase match, not a verdict.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 8–Nov 15 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/15/2026, 2:04:58 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year225 dated mentions

Observed mentions: 2016-11-26 10:24:57 UTC to 2025-11-06 22:34:08 UTC.

02040602016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments20162017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 13 mentions; 0 submissions, 13 comments2018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 9 mentions; 0 submissions, 9 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 27 mentions; 2 submissions, 25 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 52 mentions; 3 submissions, 49 comments20202021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 41 mentions; 2 submissions, 39 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 27 mentions; 3 submissions, 24 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 16 mentions; 1 submissions, 15 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 17 mentions; 2 submissions, 15 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 20 mentions; 2 submissions, 18 comments2025

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC303
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC13013
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC909
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC27225
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC52349
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC41239
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC27324
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC16115
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC17215
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC20218

What Hacker News says

3 sources
I don't think there are that many languages that are good for writing a shell. There seem to be a few shells written in Go, but Go only reluctantly supports fork(), because it interacts with its threaded runtime. Python is actually closer to what you want than Go, but I think it will end up having problems with signal handling, because the Python interpreter does its own signal handling. The prototype of my shell is written in Python [1]. Garbage collection almost always interacts poorly with signal handling. You can't interrupt a garbage collector at an arbitrary point. I wanted to bootstrap my shell [1] with Lisp -- and I hacked on femtolisp because Julia is bootstrapped in exactly this manner. And for awhile I thought about using an OCaml front end. But in the end I settled on C++ (writing 3K lines of code, which I plan to return
Read the rest
to after my prototype is done.) C++ lets you do fork(), exec() and handle signals exactly as in C, but it actually has useful string abstractions! C++ has a lot of problems, but it appears to be the best tool for this job. [1] https://github.com/oilshell/oil/
In Write a Shell in C (2015)
If you want to see a pretty complete shell in a higher level language (Python, 11K lines of code), check out: 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 inte
Read the rest
rfacing 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.)
In Write a Shell in C (2015)
Well, the practical answer that all languages I know of have separate lexical and grammatical structure. It's just easier to write if you separate them. Though it's baroque, even bash has clear lexical structure. In my code, the lexer is the foundation and doing a lot of useful work. It's a map from the 13 modes to a list of regexes, which is a lot of logic that is kept out of the parser. https://github.com/oilshell/oil/blob/master/osh/lex.py The parser just calls lexer.Read(lex_mode), which hides the complexity of all these regexes. (The lexer might look weird, but I wrote it in a style to port to C, and in particular using re2c. This is an awesome tool which I've mentioned in my blog a couple times, but not written about yet. It combines regular expressions and turns them into a bunch of gotos in C. http://www.oilshell.org/cross-re
Read the rest
f.html?tag=re2c#re2c ) ----------- For a more theoretical answer: I've had this discussion before, and I would claim that lexing and parsing should be separate because they differ in both computational power and running time. Lexing is fast but not that powerful -- you are structuring the input stream with (at most) regular expressions. It can be done in linear time, without backtracking. On the other hand, parsing is slow but more powerful, e.g. CFGs or PEGs can recognize more than regular expressions, but they require backtracking/memoization/lookahead/etc. In other words, why not do the easy work with the fast algorithm, and then do the harder work with the more complicated, expensive algorithm -- on a shorter input? I came to the conclusion several years ago that PEGs only combined lexing and parsing for reasons of academic presentation and proof. I don't think it actually helps you in practice. Hope that answered the question! I think my shell lexer is somewhat interesting so I plan to blog about it. Honestly re2c was almost the thing that inspired me to write the shell -- it would have been intractable otherwise.
In META II: A Syntax-Oriented Compiler Writing Language (1964) [pdf]

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.