[HN Gopher] Elvish - Scripting language and interactive shell
___________________________________________________________________
Elvish - Scripting language and interactive shell
Author : kartikarti
Score : 73 points
Date : 2025-04-30 11:51 UTC (4 days ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| baobun wrote:
| Anyone here using elvish on the regular? Anecdotes please!
| sidkshatriya wrote:
| I don't use Elvish daily (I use fish) but writing scripts in
| Elvish is a great experience. The elvish executable can serve
| as an LSP server and that makes writing Elvish scripts a bit
| easier.
|
| I don't care much for the Elvish shell experience, rather I
| like the Elvish scripting language. The documentation is top
| notch and the language evolves slowly and feels stable.
| einpoklum wrote:
| > I don't care much for the Elvish shell experience, rather I
| like the Elvish scripting language.
|
| It's a shell, aren't those two things supposed to be the same
| basically? Or - do you mean the interaction with the
| terminal/command-line?
| sidkshatriya wrote:
| The shell prompt is also a small interface. How your shell
| responds to tab autocomplete, provides suggestions etc. can
| be quite helpful. Here I just like the way fish suggests
| filenames, provides an underline for filenames that exist
| and so on.
|
| The language is what you write in an $EDITOR. Here Elvish
| scripts can be nice, succinct and powerful. I like how I
| don't have to worry about strange "bashisms" like argument
| quoting etc. Everything feels consistent.
| IshKebab wrote:
| Looks nice. Obviously way better than Bash, but there are a few
| options that are way better than Bash, so I feel like it should
| spend some time convincing me why I should use this over e.g.
| Nushell.
|
| Anyone have any experience of both?
| sidkshatriya wrote:
| nushell vs Elvish
|
| The Nushell and Elvish scripting languages are similar in many
| ways. I personally find the "shell" experience better in
| Nushell than Elvish.
|
| Nushell
|
| - Bigger community and more contributors
|
| - Bigger feature set than Elvish
|
| - Built in Rust (Yay :-)! )
|
| Elvish
|
| - Mostly developed by one person
|
| - Built in golang
|
| - Amazing documentation and general attention to detail
|
| - Less features than Nushell
|
| - Feels more stable, polished, complete than Nushell. Your
| script written today more likely to work unaltered in Elvish a
| year down the line. However this is an impression. Nushell must
| have settled down since I last looked at it.
|
| For "one off" scripts I prefer Elvish.
|
| I would recommend both projects. They are excellent. Elvish
| feels less ambitious which is precisely why I like it to write
| scripts. It does fewer things and I think does them better.
|
| Nushell feels like what a future scripting language and shell
| might be. It feels more futuristic than Elvish. But as
| mentioned earlier both languages have a lot of similarities.
| graemep wrote:
| > Built in Rust
|
| > Built in golang
|
| Does that matter?
|
| If you intend to be a contributor, of course the chosen
| language matters, but only a very small proportion of users
| will be contributors.
| dijit wrote:
| There are quirks specific to languages.
|
| Rust _tends_ to be marginally faster and compile to smaller
| binaries.
|
| Go projects tend to hit maturity faster and develop
| quicker.
|
| Its a relevant factor to quickly stereotype certain
| characteristics of development, but its not anywhere close
| to important.
| IshKebab wrote:
| I don't think it matters whether it's Rust or Go
| especially, for an end user tool. But it definitely matters
| if it's Rust/Go compared to something else like C or
| Python.
|
| The language choice has certain implications and I would
| say Rust & Go have fairly similar implications: it's going
| to be pretty fast and robust, and it'll have a static
| binary that makes it easy to install. Implications for
| other languages:
|
| C: probably going to have to compile this from source using
| some janky autotools bullshit. It'll be fast but segfault
| if you look at it funny.
|
| Python: probably very slow and fragile, a nightmare to
| install (less bad since UV exists I guess), and there's a
| good chance it's My First Project and consequently not well
| designed.
| graemep wrote:
| Not even that matters to me: I will install from repos.
| It might make packagers' lives a bit more difficult in
| some cases but they are probably very familiar with that.
|
| I have not really had problems with installing C (on the
| rare occasions I have compiled anything of any
| complexity) nor Python applications. Xonsh is supposed to
| be pretty good and written in Python, and most existing
| shells (bash, zsh, csh etc.) are written in C.
|
| Amusing aside, I use fish and until I decided to fact
| check before adding it to the list of shells written in
| C, I did not realise it was written in Rust.
| IshKebab wrote:
| Fish switched from C++ to Rust really recently.
|
| https://fishshell.com/blog/rustport/
| graemep wrote:
| That is impressive.
|
| Now you mention it I vaguely recall reading something
| about it somewhere as planned but its been done!
| Levitating wrote:
| What about fish? I've enjoyed using it for years.
|
| There's a few obvious features missing in fish like
| backgrounding an alias or an equivalent to set -e, other than
| that I have no complaints.
|
| The first thing I do on any machine is install fish.
| sidkshatriya wrote:
| fish is amazing. I use it as my primary shell.
|
| But for writing scripts I would reach for Elvish/Nushell.
| More powerful.
| atiq-ca wrote:
| Looks interesting! Does it have OOP features kinda like how
| powershell has that?
| photonthug wrote:
| While removing weird stuff from daily bash annoyances is
| interesting, I'm not necessarily looking to replace that with
| brand new but also pretty random weird stuff. Adding new rules
| isn't the same as adding structure. The documentation is also
| frequently strange in a way that makes it hard to digest. From
| https://elv.sh/learn/first-commands.html#external-commands
|
| > While Elvish provides a lot of useful functionalities as
| builtin commands, it can't do everything. This is where external
| commands come in, which are separate programs installed on your
| machine. Many useful programs come in the form of external
| commands, and there is no limit on what they can do. Here are
| just a few examples: Git provides the git command to manage code
| repositories
|
| At first I thought, wait, is this a shell or not, do I have to
| write code or something to get access to normal external
| commands? But no, this is more like going to a car dealership and
| having the salesman say "Hey thanks for coming by, a car is a
| mechanical device consisting of metal parts and rubber parts for
| the purpose of taking you where you need to go! Now that we're on
| the same page about that, money is a thing made of paper for the
| purposes of .."
|
| Docs are hard, once or twice is fine, but lots of parts are like
| this and I gave up reading. Not sure if it's AI generated, but if
| the project is doing that then it should stop, and if it's not
| doing that it should consider starting to
| nneonneo wrote:
| I mean, you are literally reading the first chapter of the
| tutorial for beginners ("Beginner's Guide to Elvish is for you
| if you haven't used shells a lot or want to brush up on the
| basics").
|
| They have a separate set of docs for people who do have some
| experience with other shells (https://elv.sh/learn/); you may
| find the quick tour more suitable for your speed:
| https://elv.sh/learn/tour.html
| photonthug wrote:
| I did browse around, that's the page I got the first part of
| my comment from. Modules are one example of something that
| sounds probably good
| (https://elv.sh/ref/language.html#modules ). Good stuff is
| really weakened though by the many random changes that seem
| to go from arbitrary to.. also arbitrary, while destroying
| any chance of readability, backwards compatibility, or
| interoperability. Why?
|
| > Line continuation in Elvish uses ^ instead of \
|
| > Bash: echo _.[ch] vs Elvish: echo_.?[set:ch]
|
| One more example, guess what this does: `echo &sep=',' foo
| bar`. Is it bash, elvish? Some combination of the two with
| markdown? Legal in all three? Elvish certainly cleans up
| conditionals and stuff, but you probably shouldn't introduce
| new things with exactly the same name _unless_ you 've
| created a genuine superset/dialect where the older version
| still works without rewrite. Namespace it as elvish.echo or
| use your module system. Shadows aren't friendly, this is
| equivalent to the guy that monkey-patches
| sys.stderr=sys.stdout to work around their one-off problem
| layer8 wrote:
| Elvish is designed for use on Windows as well, where \ is
| the directory separator and wouldn't be uncommon to occur
| at the end of a command line, so that can't be used for
| line continuation. Windows (and DOS?) batch files use ^ for
| line continuation, so that's probably where it was adopted
| from.
| rendaw wrote:
| I went down this route based on HN recommendations, with some
| people calling it stable well documented.
|
| There's TODOs all over the documentation! There's no background
| task tools for scripting, and in interactive use background tasks
| are barely supported - an issue about background tasks has people
| going roughly "nobody needs to do tasks in parallel, that was
| only important when people were working on mainframes". The shell
| hooks have (undocumented) weird restrictions. Lazy iteration of
| lists is only supported by using functions with callbacks. Stable
| = development appears stopped.
|
| This is half baked and dead. For my new computer I really
| _really_ wanted a lightweight new shell with orthogonal syntax
| thought out from the ground up and not glued together over 4
| decades, and this seemed like the closest option! But this isn 't
| it.
| nerdponx wrote:
| The big one for me is no string interpolation, as a deliberate
| design choice.
| em-bee wrote:
| what can string interpolation do that i can't also do by
| sandwiching a variable between strings:
| 'string1'$var'string2'?
|
| string interpolation is useful where concatenating strings
| requires an operator, but i don't see the benefit otherwise.
|
| for more complex examples i can use printf, or someone could
| write a function that does string interpolation. since there
| is no need to fork, that should not be that expensive
| layer8 wrote:
| I mostly agree, but in Bash for example
| "string1${var}string2" guarantees to be a single argument,
| which 'string1'$var'string2' doesn't (when $var contains
| whitespace). So it entails certain other language design
| choices.
| em-bee wrote:
| in bash yes, so that makes sense. thanks for pointing
| that out. in elvish $var is guaranteed to remain one
| string, and so 'string1'$var'string2' is always going to
| remain one argument too.
| onli wrote:
| Oil shell (now oils) was too close to bash for your goal?
| rendaw wrote:
| I think I didn't look at it initially because it was too
| close to bash, and then by the time I burned out on fully
| reimagined shells I fell back to zsh which was the shell I
| knew supported post-command hooks. Definitely not a final
| decision, but it might be a while before I try new shells
| again...
| chubot wrote:
| FWIW Oils has two modes, and I wrote new landing pages for
| them recently:
|
| _Nine Reasons to Use OSH_ - https://oils.pub/osh.html - it
| runs existing shell scripts, ...
|
| _What is YSH?_ - https://oils.pub/ysh.html - It's the
| ultimate glue language, like shell + Python + JSON + YAML,
| seamlessly put together
| rahen wrote:
| If by any chance you're an Emacs user, check out Eshell. It
| blends Elisp macros with shell commands, and since it keeps the
| buffer model, you can use all the usual Emacs tools for
| searching, sorting, and more. It's a unique shell with some
| learning curve, but it's mature and powerful.
|
| https://www.youtube.com/watch?v=9xLeqwl_7n0
| hnlmorg wrote:
| There's also a lot of good design that's gone into Elvish. And
| I don't think it's fair to call it "dead" when the maintainers
| for Elvish are active both on Github and here on HN too
| (probably other places too).
|
| However if you're looking for an alternative then there's:
|
| - Murex (disclaimer: I'm one of the maintainers) which does
| support background processes and has extensive documentation.
| https://murex.rocks
|
| - Nushell: I'm not personally a fan of its design choices but
| it has a large following of people who do really enjoy it so it
| might also appeal to yourself too.
|
| As for Elvish, I do encourage others to give it a go
| themselves. It's really well thought out and what might be a
| deal breaker for some people isn't for others.
| rendaw wrote:
| Elvish had some very cool ideas, which is why I tried it out!
| Like the built in script checker! But it also has a lot of
| very basic issues that have been open for years, and TODOs in
| the documentation as I mentioned. People are going to read
| your message and put N hours into it and get burned, and I
| think this is a fair warning.
|
| Nushell also had very minimal background task support, so I
| rejected that. They explicitly say use some other program for
| background tasks in their docs.
|
| I actually looked at Murex after seeing it in previous
| threads, but I bounced for some reason... I just took another
| look though skipping the tutorial and I see you have `bg` and
| `fg` support! But does `bg` return the `fid`? Can you use
| those in scripts, or are they hobbled the same way bg/fg are
| in bash?
|
| It's been a good 4-5 months since I went down this rabbit
| hole, but IIRC the basic things I wanted to do and got
| blocked in multiple shells were:
|
| - System-wide interactive-use config file, I use Nixos and
| manage my system config using that
|
| - Background task support - I need to start an ssh tcp proxy,
| pipe a command over it, then kill ssh once the command is
| done (all in a script).
|
| - Post-command hook, to send a notification when a long
| command finishes
|
| - Async iteration of command output, i.e. streaming events
| with swaymsg subscribe and running a command when certain
| events occur
|
| - Value/call arity safety - i.e. a clear distinction between
| a single value and multiple values that doesn't rely on
| stringification hacks. I.e. in `command $x` `command` should
| always have one argument, regardless of the contents of `x`,
| and making that plural should be explicit.
|
| And then other standard evaluation criteria, like I looked at
| xonsh but it seemed like a massive hack, despite handling a
| lot of the above.
| hnlmorg wrote:
| > does `bg` return the `fid`
|
| There's two kinds of process IDs in Murex: FID (function
| IDs) and PID (process IDs)
|
| Forking is expensive in POSIX and has a number of drawbacks
| such as the inability to share scoped variables without
| resorting to environmental variables. So a FID is basically
| a PID but managed inside the scope of Murex's runtime. You
| can manage FIDs in much the same way as you can manage
| PIDs, albeit using Murex builtins rather than coreutils
| (though PID management tools in Bash are technically
| builtins rather than coreutils too).
|
| What this means in practice is you can have entire blocks
| of code pushed into the background, eg >>
| GLOBAL.name = "rendaw" >> bg { sleep 5; echo "Hello
| $name" }; echo "not bg" not bg Hello rendaw
|
| You can see the FID as well as the job ID the usual way,
| via `jobs` >> jobs JobID
| FunctionID State Background Process Parameters
| %1 2109 Executing true exec sleep 5
|
| ...and you can kill that entire `bg` block too
| fid-kill 2109
|
| But you'd also see any non-builtins in `ps` too:
| >> ps aux | grep sleep hnlmorg 72749 0.0 0.0
| 410743712 1728 s012 S+ 4:24p.m. 0:00.00
| /usr/bin/grep --color=auto sleep hnlmorg 72665
| 0.0 0.0 410593056 432 s012 S+ 4:23p.m. 0:00.00
| /bin/sleep 5
|
| > Can you use those in scripts, or are they hobbled the
| same way bg/fg are in bash?
|
| While the above seems very complicated, the advantage is
| that `bg` and `fg` become much more script friendly.
|
| > - System-wide config file, I use Nixos and manage my
| system config using that
|
| This isn't Murex's default behaviour but you could easily
| alter that with environmental variables:
| https://murex.rocks/user-guide/profile.html#overriding-
| the-d...
|
| The latest version of Murex (v7.0.x), which is due to be
| released in the next few days, makes this even easier with
| a $MUREX_CONFIG_DIR var that can be used instead of
| multiple specific ones.
|
| > - Background task support - I need to start an ssh tcp
| proxy, pipe a command over it, then kill ssh once the
| command is done (all in a script).
|
| Murex has another layer of support for piping in addition
| to those defined in POSIX, which are basically channels in
| the programming language sense. In murex they're called
| "Murex Named Pipes" but the only reason for that is that
| they can be used as a glue for traditional POSIX pipes too.
| This is one area where the documentation could use a little
| TLC: https://dev.murex.rocks/commands/pipe.html
|
| > - Post-command hook, to send a notification when a long
| command finishes
|
| There are two different events you can hook into here:
|
| - onPrompt: https://dev.murex.rocks/events/onprompt.html
|
| This is similar to Bash et al prompt hooks
|
| - onCommandCompletion:
| https://dev.murex.rocks/events/oncommandcompletion.html
|
| This hooks into any command _name_ that 's executed. It
| runs the comment in a new TTY and buffers the command's
| output. So, for example, if you want a command like `git`
| to automatically perform a task if `git push` fails with a
| specific error message, then you can do that with
| onCommandCompletion.
|
| > - Async iteration of command output, i.e. streaming
| events with swaymsg subscribe and running a command when
| certain events occur
|
| I'd need to understand this problem a little more. The
| channels / Murex Named Pipes above might work here. As
| might onCommandCompletion.
|
| > - Value/call arity safety - i.e. a clear distinction
| between a single value and multiple values that doesn't
| rely on stringification hacks. I.e. in `command $x`
| `command` should always have one argument, regardless of
| the contents of `x`, and making that plural should be
| explicit.
|
| This one is easy: scalars are always $ prefixed whereas
| arrays are @ prefixed. So take the following example:
| array = %[ a b c ] >> echo $array
| ["a","b","c"] # a single parameter representation of the
| array >> echo @array a b c #
| the array expanded as values
|
| -----
|
| This is quite a lengthy post but hope it helps answer a few
| questions
| ghthor wrote:
| There is ysh
| rendaw wrote:
| Arrg, s/lazy/async/.
|
| Just to add some further qualification, I was fully prepared to
| learn something from the ground up, throw away all my
| preconceptions, and give some weirdness a try - including no
| string interpolation. I wanted to 100% replace bash, both as a
| shell and for scripting everywhere. I was exactly Elvish's
| target user.
| em-bee wrote:
| it's still under development, but it most certainly isn't dead.
| it's stable in that development is not disruptive. i use it as
| a daily driver.
|
| you are right about lack of support for job control, it's
| annoying. but my understanding is that the problem seems to be
| a difficulty in implementing job control with go. when people
| say nobody needs parallel tasks that doesn't make sense because
| you can run jobs in the background. you just have to do it
| explicitly before starting, and you can't switch back and
| forth. yes, that's a problem, and for me it is one of the most
| annoying missing features. but it comes up seldom enough that
| it doesn't disrupt daily use for me. which is to show that the
| things i need for daily use are all there.
| account-5 wrote:
| Ever since I 'discovered' Nushell I've noticed a lot of new
| shells appearing on HN.
|
| The thing I like about Nushell is it does away with some of the
| things that I found hard with bash, and made data formats a first
| class citizen (something I enjoyed about powershell).
|
| I think if you like Lisp elvish would be ideal but for me the
| lack (seeming, I've not done a deep dive on the docs) of built-in
| data parsing is a no.
| srott wrote:
| Elvish was a bit slow to me, nush is nice but I found out I can
| do most of the tasks using yq and jc more intuitively.
| linsomniac wrote:
| I've been eyeing a "better shell" for a while, but I've just
| decided that a couple zsh plugins and I'm probably happiest. As
| the meme says "Change my mind".
|
| I've been using fish for the last year or more, and I like some
| of the "batteries included", particularly the predicting of the
| command you want to run. But fish is too much like bash in
| syntax, meaning that I just think of it like bash until I have to
| type "(foo)" instead of "$(foo)", or "end" instead of "fi". The
| zsh plugins for doing command predicting and fancy prompt seems
| to get me all the fish benefits with none of the rough spots.
| And, frankly, the changes fish does doesn't seem to have any
| benefit (what is the benefit of "end" over "fi").
|
| Even xonsh (I'm a huge Python fan) doesn't really have enough
| pull for me to stick in it. Oils, nu, elvish, they all have some
| benefits for scripting, but I can't see myself switching to them
| for interactive use.
|
| It's kind of feeling like zsh is "good enough" with no real
| downsides. Maybe this is mostly that I've been using
| sh/ksh/bash/zsh for 40 years, some of these other shells might be
| easier to switch to if you lack the muscle memory?
| 3PS wrote:
| > But fish is too much like bash in syntax, meaning that I just
| think of it like bash until I have to type "(foo)" instead of
| "$(foo)", or "end" instead of "fi"
|
| Note that fish does also support bash's "$(foo)" syntax and has
| for a few years now.
| linsomniac wrote:
| Ooh, good to know!
| em-bee wrote:
| supporting more and more bashisms is what makes fish less
| attractive for me. i used fish for years. $(foo) in bash
| forks a subshell. in fish it doesn't. i am not a fan of
| supporting different syntaxes to do the same thing. if they
| had implemented $() to fork a subshell, that might have made
| some sense, but otherwise it is just redundant. learning to
| use () instead of $() or `` really isn't hard. so why?
| tasuki wrote:
| What plugins? And where is your zsh config?
|
| (Ftr, I've been using zsh for maybe 5-8 years, managed to avoid
| oh-my-zsh, and only use 'zsh-autosuggestions' and 'zsh-syntax-
| highlighting' plugins. I've customised a theme to suit me, but
| barely know anything about zsh to be honest...)
| linsomniac wrote:
| Well, pretty much what you said: syntax-highlighting, oh-my-
| zsh, git, command-not-found, autosuggestions, atuin, zoxide,
| and zsh-vi-mode. These days, I'm looking for as little stuff
| that I have to maintain myself as possible.
| Arcuru wrote:
| I've been using fish for many years now though I keep trying all
| these new shells.
|
| Ultimately I've found that for my interactive shell I just want
| something widely supported and with easy syntax for `if` and
| `for` loops for short multi-line commands. For anything longer
| than that I just reach for real Python using either the `sh` or
| `plumbum` package.
|
| I don't need the extra features very often, so I just run things
| in full Python where I'm already comfortable.
|
| I've tried oils/ysh, elvish, xonsh, nushell, and while they are
| _fine_ I don't want to learn a different language that's not
| quite Python and not quite shell.
| dang wrote:
| Related. Others?
|
| _Elvish, expressive programming language and a versatile
| interactive shell_ -
| https://news.ycombinator.com/item?id=40316010 - May 2024 (114
| comments)
|
| _Elvish Scripting Case Studies_ -
| https://news.ycombinator.com/item?id=39549902 - Feb 2024 (1
| comment)
|
| _Elvish is a friendly interactive shell and an expressive
| programming language_ -
| https://news.ycombinator.com/item?id=24422491 - Sept 2020 (49
| comments)
|
| _Elvish: a shell with some unique semantics_ -
| https://news.ycombinator.com/item?id=17987258 - Sept 2018 (1
| comment)
|
| _Elvish 0.11 released_ -
| https://news.ycombinator.com/item?id=16174559 - Jan 2018 (1
| comment)
|
| _Elvish: friendly and expressive shell for Linux, macOS and
| BSDs_ - https://news.ycombinator.com/item?id=14698187 - July 2017
| (86 comments)
|
| _Elvish - An experimental Unix shell in Go_ -
| https://news.ycombinator.com/item?id=8090534 - July 2014 (75
| comments)
___________________________________________________________________
(page generated 2025-05-04 23:01 UTC)