Skip to content(if available)orjump to list(if available)

Xonsh – A Python-powered shell

Xonsh – A Python-powered shell

49 comments

·February 21, 2025

dang

Related:

Xonsh: Python-powered, cross-platform, Unix-gazing shell - https://news.ycombinator.com/item?id=39368586 - Feb 2024 (102 comments)

Ask HN: Does anyone use xonsh shell? - https://news.ycombinator.com/item?id=34449879 - Jan 2023 (3 comments)

Xonsh: I don't remember how to write a for loop in Bash [video] - https://news.ycombinator.com/item?id=33044772 - Oct 2022 (130 comments)

Xonsh is a Python-powered shell - https://news.ycombinator.com/item?id=30457791 - Feb 2022 (3 comments)

Xonsh is a Python-powered shell - https://news.ycombinator.com/item?id=30442016 - Feb 2022 (1 comment)

The Xonsh Python Shell - https://news.ycombinator.com/item?id=24744653 - Oct 2020 (41 comments)

Xonsh: Python-powered, cross-platform, Unix-gazing shell - https://news.ycombinator.com/item?id=17989710 - Sept 2018 (93 comments)

Xonsh: a Python-ish, BASHwards-looking shell language and command prompt - https://news.ycombinator.com/item?id=11836893 - June 2016 (2 comments)

The xonsh shell - https://news.ycombinator.com/item?id=11672023 - May 2016 (53 comments)

Xonsh, a Python-ish, Bash-compatible shell language and command prompt - https://news.ycombinator.com/item?id=9207738 - March 2015 (61 comments)

foundry27

I’ve been using xonsh as my daily driver for a few years now, and it’s a massive productivity booster!

Broadly speaking I’ve found that most of the reported compatibility and usability concerns in their GitHub issues have boiled down to user error, rather than any kind of a defect with the shell itself. That’s not to say there aren’t any issues, but they’re few and far between, and it’s more than solid enough for regular use. It isn’t bash, and you shouldn’t expect to execute a bash script with xonsh or use bash idioms (even though some compatibility layers exist for e.g. translating your ~/.bashrc and sourcing envvars from bash scripts).

ambivalence

Xonsh is a fantastic shell. I literally think they are most hindered by the name at this point, since it's one of those clever names that are pronounced in a peculiar way and one that doesn't convey too well that it's really Python + sh in a beautifully consistent design.

It's very easy to switch if you're willing to spend 30 minutes to go through this talk about its design by the author: https://www.youtube.com/watch?v=uaje5I22kgE

After this short intro you will know how Python and shell interact within xonsh and you'll avoid surprises.

I wish it started faster, but it's a really small price to pay for having Python 3.13 open literally at all times.

voidfunc

I've been mispronouncing it for years as Zonsh... it's Consh.. doh

js2

I'm from S Florida where the conch shell is pronounced konk. It pains me to pronounce xonsh as kontch. Maybe I'll just go with calling it zonk. :-)

agalunar

People may also be interested in the Tako shell, which is a fork of Xonsh that “sacrifice[s] some of the ‘fancy stuff’ so that basic shell operations work as expected, the codebase is small, and things are as performant as can be expected from a shell written in Python.”

(Homepage) https://takoshell.org/index.html

(Differences from Xonsh) https://takoshell.org/xonsh.html

ambivalence

Not impressed with tako. Replaces the BSD license with GPL for mostly removing functionality and reverts.

It looks unmaintained. Last release 5 years ago, documentation is sporadic.

Reminds me of some of the angry forks of Black that get like 100 downloads a year.

fadesibert

I liked the idea of tako - a slightly slimmed down, less clunky, version of Xonsh. However, it requires significant patching in order to work with modern python (I tried with 3.12, but I believe some of the breaking changes occur in 3.9+).

Specifically, there are a number of imports from collections which appear to no longer work, and I had to install a fairly old version of collections to get Set and MutableSequence (which `tako/takoshell/tools.py` subclasses).

`hz.mit.edu` is not a git forge, so I don't think I can submit a PR without e-mailing the author.

BeetleB

I've used xonsh as my primary shell since around 2017. It's awesome. Being able to write shell scripts in something very similar to Python is awesome. Bash scripting is the epitome of "not awesome".

totalhack

This is slightly less interesting now that I can have AI remember bash script syntax for me.

brumar

I would not advise to replace your interactive shell with it as it's a pain when you stumble upon uncompatible commands, but writing shell scripts with xonsh is a wonderful experience.

poincaredisk

I use fish, so it's not a problem for me. When I tried it 4 years ago it's was a bit unstable, which made me switch back to fish. Also fish is much more polished and user friendly out of the box.

scottydelta

Can you talk about how is it different than writing python scripts? Or writing test code in the python console?

Neywiny

Feels like the only benefit is not having to write os.system(). Though maybe including shell scripts (like build environment setup stuff from other software) for more complicated commands? I may give this a try for a bit to find out

timonoko

This the perfection, why would you want anything more?

  import os
  def sh(x):
      return os.popen(x).read().split("\n")

shlomo_z

os.system doesn't actually change your environment:

    >>> os.getcwd()
    'C:\\Users\\Admin\\Downloads'
    >>> os.system("cd Video")
    0
    >>> os.getcwd()
    'C:\\Users\\Admin\\Downloads'
    >>>

BeetleB

In a xonsh script, you can have regular statements like "cd", "ls", and pretty much everything.

It's just like Bash scripting, except in Python. You can mix and match Python statements with regular shell commands.

echoangle

I have never tried it but I would probably prefer to use sh ( https://pypi.org/project/sh/ ) and have users install that before having to use a totally separate shell. Python is normally already there.

brumar

For me it shines when you need to write shell scripts but you prefer do some parts in python. As another commenter wrote os.system or calling the subprocess module works too, but I find it less satisfying.

Qem

What are some examples of incompatible commands?

brumar

I don't remember exactly why and how some shell scripts refused to run, but on top of my head I think 'alias' was not working and 'sudo !!' too.

BeetleB

I hope you're not trying to source regular Bash scripts without using source-bash.

I've used xonsh as my primary shell for many years now. The Bash compatibility was poor initially, but they fixed most/all the issues, and source-bash just works.

I use Gentoo, and don't actually use sudo, so I can't comment on that (I just su into root).

rendaw

I'm rebuilding my computer and going through around 15 years of linux improvements in the course of a couple weeks, and this week I'm hunting for bash replacements (bash won't let me automatically run a command before and after each interactive command I execute, which I want for task completion notifications).

There are a lot of new shells, but despite the overwhelming positivity of each thread here they've each been super incomplete/half baked. FWIW I'm looking for a non-posix de-crufted (no oil shell, no zsh) and lightweight/minimal (no fish) shell.

I haven't tried all of these out significantly (really diving in takes hours if not days) but considering my use cases and thoroughly reading the documentation/field reports:

Elvish seemed really cool but has no async/background task support. Furthermore AFAICT you can't iterate over the output of a process _while_ it's running. There are bugs (can't import edit module), there's TODO all over the docs despite supposedly being mature and stable, etc.

Nushell also has no async/background task support (pueue doesn't count, running in separate process trees has countless implications).

Ion shell sounds great on paper, but it's missing the entire first 2-3 chapters of its documentation. It doesn't seem to have any significant background job control, and seems more like a paper-overing of shellisms than a reinvention.

So xonsh seems like the best remaining competitor. It supports background processes with `Popen`, but I can't find an example for async iterating lines. I see lots of examples that are like, `for x in !(ls)` or `for x in $(whatever).splitlines()` but both of those require the command to finish before executing the loop.

Then I keep seeing reports of Ctrl+C breaking with loops, all the python module and environment dependency management madness (plus cross contamination), excessive slowness when mixing python and commands, etc etc.

I'd like to hear a critical rebuttal of these but I think these new shells are more intellectual curiosity than an actual step up. I'm probably going to give up and go with zsh, which while not an improvement at least it will do what I need I don't have to learn anything new.

One thing I've learned though is that although amazing testimony, being someone's main driver isn't a good enough review. Heck, bash has been my main driver for 15 years and it's _awful_. You learn the pain points and then subconsciously avoid doing anything with it near those points.

isr

> (bash won't let me automatically run a command before and after each interactive command I execute, which I want for task completion notifications

Not to put you off investigating alternative shells (I've spent time with rc shell, xonsh (and tako), and even turned gauche scheme & tcl into a commandline shell), but isn't your bash problem solved by using $PS1 to launch your own functions to do whatever?

At least, you can use $PS1 for the "after command" bit. For pre-command, just use a simple 1 letter wrapped script which does whatever, and then exec's the remaining arguments (aka "Bernstein chaining")

(unless I've gotten the wrong end of the stick, and am missing what you meant)

rendaw

No, not at all! Yeah I could do that, and it's something I considered, but I feel like working in a shell shouldn't be such an unrelenting hack. FWIW I think every shell _but_ bash supports it, I was just hoping to move to something that's overall nice to use in the process.

belden

I wonder if bash-preexec https://github.com/rcaloras/bash-preexec could be used here.

Perhaps you could start a timer in a preexec, and stop it in precmd. If the elapsed time is greater than some value, notify-send yourself a message that a long-running command has finished.

shiomiru

Another solution for the pre-command part is "trap 'some command' DEBUG".

isr

Didn't know about that. Thanks!

lloeki

> bash won't let me automatically run a command before and after each interactive command I execute, which I want for task completion notifications

Incorrect. This can be achieved because I've done it ;)

It relies on trap DEBUG (preexec) and PROMPT_COMMAND (precmd), but to make this much easier for me I've ported zsh preexec and precmd callback support to bash:

https://github.com/lloeki/dotfiles/blob/master/bash/ext

Then with those callbacks now available it is quite easy to e.g compute time between command start and command end:

https://github.com/lloeki/dotfiles/blob/master/bash/rc

(The time thing is commented out because I don't need it right now, I used it to display command exec time on the prompt. Note that bash EPOCHREALTIME has second-level precision)

And from there notifying completion of commands that run longer than X is absolutely trivial.

Other things I've "backported":

- chpwd callback

- the %\n thing on lack of newline in command output

- PROMPT and RPROMPT

- zprompt colors

ratorx

I’m curious what metric you’re evaluating minimality with?

Naively I’d expect Fish to seem more minimal than something like xonsh (which embeds the entirety of Python).

pmarreck

> all the python module and environment dependency management madness (plus cross contamination)

this was a complete python non-starter for me as soon as I encountered it a couple of times, and it mystifies me how others tolerate this crap

arcanemachiner

> bash won't let me automatically run a command before and after each interactive command I execute, which I want for task completion notifications

I remember seeing some simple CLI program that you could pipe your task into, and it would notify you when the task completed. the names escapes me at the moment.

null

[deleted]

rendaw

I mean I can do `; notify-send done` too, but I forget (when it's most critical)

bb88

I used it for a few months a couple years back, and when I got a new machine, I never bothered to reinstall it. Honestly bash pipes and the gnu utils are often more powerful for what I need on a day to day basis. And if I need something more powerful, I'll break out python explicitly.

pasc1878

xonsh includes pipes and easily call any command line program.

and you have python added on

aterp

Might be interesting to folks in this thread - I'm working on a CLI tool/language which aims to let people write better scripts, more easily. It integrates well with Bash if it's needed, but lets you to avoid writing whole scripts in Bash and particularly some of the more painful aspects like arg parsing.

This page gives a bit of a preview, plus there are some links at the bottom to additional features. Still under development tho!

https://amterp.github.io/rad/guide/getting-started/

ambivalence

Work on what you want, so don't let me deter you. But in my personal case, what pushed me from fish to xonsh was that I could never quite internalize the way it wanted to do functions, if statements (and tests inside them) and loops.

Once you were reading code, it made sense for the most part. But when I had to write a new multiline command or a script, I had to look things up in documentation constantly. For my brain "similar but different" was torture, not an advantage.

With Xonsh you get real Python and this solves all my problems. As soon as you learn what $VAR, $(CMD), and @EXPR do, you're good to go!

aterp

I hear you, real Python has its benefits :) The way I see it, these are different approaches to solving similar (but still quite different) problems. In the case of rad, it's just a language, it's not trying to replace your shell, but the fact that it's only Python-like might indeed deter some people. But - it also opens up some unique syntax that can be tailored really well to CLI scripts. For example, the syntax for args [1] or json "rad blocks" [2], as I've called them.

[1] https://amterp.github.io/rad/guide/args/#arg-declarations

[2] https://amterp.github.io/rad/guide/rad-blocks/#basic-example

oguz-ismail

Is composability not a goal of this language? Like how do you capture the output of an if block? Or how do you suppress one's output while retaining other side effects like variable assignments?

aterp

Don't think I'm understanding what you mean - composability of what exactly? It's a very Python-like language, so if-blocks behave like they do in Python/C, etc. Suppressing one's output: are you referring to invoking shell commands? Each shell invocation (at the moment) happens in its own session, independent of others, so variable assignments really only matter if you're basically embedding a shell script in RSL as e.g. a multiline string, and then invoking it. But I might be misunderstanding what you mean!

oguz-ismail

Oh, it's not like what I thought then. Okay

ipnon

The ergonomics look excellent. The most important factor for a shell is getting out of the way! Users shouldn’t be thinking about their shell syntax, and it seems this has been achieved.

kseistrup

Marcel the Shell is another shell/python hybrid: https://www.marceltheshell.org/