Scripting is More Fun With Nushell
There are multiple ways to improve your experience in the terminal. You can get a nice prompt with starship. On Linux and macOS, you can switch to the fish shell. A lot of nice things like syntax highlighting, tab completion with help text and inline suggestions simply work out of the box.
However, I went for Nushell. Unlike fish, Nu also works on Windows. Nuโs interactive experience is nearly as nice as fishโs out-of-the-box and just as nice with a few configuration tweaks. Since I donโt use Windows as my daily driver that shouldnโt matter all that much to me, but it can be an extra benefit.
Another common way of use case of shells is for scripting.
After experimenting with commands in your terminal, you put the very same commands in a text file.
In the case of Nu, you then execute that script with nu script.nu.
This is the workflow where shells shine, and Nu is a prime example for that.
So letโs take a look at the pitch on Nuโs homepage:
Nu pipelines use structured data so you can safely select, filter, and sort the same way every time. Stop parsing strings and start solving problems.
When I first read this, it didnโt really resonate with me. Maybe I didnโt write enough shell scripts at that time.
Extract the Top Issues From a Repository
Section titled โExtract the Top Issues From a RepositoryโLetโs look at a non-trivial example to find out why itโs a big deal that Nu deals with structured data. Some GitHub repositories like Zedโs have an issue that shows the issues with the highest number of ๐ reactions created within in the last week.
We will now do the same with the help of Nushell.
I will use the Pixi repository, but any other repository with enough community engagement will do as well.
let repo = "prefix-dev/pixi"Many modern CLI tools have a JSON interface and gh is not different.
We need the following fields:
createdAtso we only take the ones from last weekreactionGroupsso we can extract the ๐ reactionstitleandurlto display them later
In the end we will get a list of records also known as a table. Each record represents one issue, and we pick one in order to get familiar with the structure. Please note that this will return a different issue for you, since more issues will have been opened on this repo by the time you read this.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| get 1โญโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎโ createdAt โ 2025-08-29T13:11:13Z โโ โ โญโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฎ โโ reactionGroups โ โ # โ content โ users โ โโ โ โโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โโ โ โ 0 โ THUMBS_UP โ โญโโโโโโโโโโโโโฌโโโโฎ โ โโ โ โ โ โ โ totalCount โ 1 โ โ โโ โ โ โ โ โฐโโโโโโโโโโโโโดโโโโฏ โ โโ โ โฐโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโฏ โโ title โ Ability to split pixi.lock (not toml!) into multiple files โโ url โ https://github.com/prefix-dev/pixi/issues/4467 โโฐโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏNotice that Nu pretty prints the record per default.
Only take Issues From Last Week
Section titled โOnly take Issues From Last WeekโNu also has first class support for datetime objects.
This makes it easy to only take the rows of our table where createdAt falls within the last week.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| get createdAt| last 5โญโโโโฌโโโโโโโโโโโโโโโโโโโโโโโฎโ 0 โ 2025-08-25T11:28:37Z โโ 1 โ 2025-08-25T10:19:22Z โโ 2 โ 2025-08-25T10:07:58Z โโ 3 โ 2025-08-25T07:21:52Z โโ 4 โ 2025-08-24T17:00:35Z โโฐโโโโดโโโโโโโโโโโโโโโโโโโโโโโฏWe took the last 5 elements. Considering that this blog has been written on August 31st, these results seem pretty reasonable.
Extract the ๐ Reactions
Section titled โExtract the ๐ ReactionsโWe donโt have a nice way to extract the ๐ reactions yet, so letโs work on that.
As a reminder, thatโs how reactionGroup value looks like for the issue we looked at originally.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| get 1| get reactionGroupsโญโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฎโ # โ content โ users โโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโคโ 0 โ THUMBS_UP โ โญโโโโโโโโโโโโโฌโโโโฎ โโ โ โ โ totalCount โ 1 โ โโ โ โ โฐโโโโโโโโโโโโโดโโโโฏ โโฐโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโฏThis issue, however, does not have reactions at all.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| get 0| get reactionGroupsโญโโโโโโโโโโโโโฎโ empty list โโฐโโโโโโโโโโโโโฏLetโs insert a new column thumbsUp, which is based on the column reactionGroup.
Of this reaction table, it only takes rows with THUMBS_UP reaction.
Rows that donโt have any THUMBS_UP reactions will result in an empty list.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| insert thumbsUp { $in.reactionGroups | where content == THUMBS_UP}| get thumbsUp| first 5โญโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎโ 0 โ [list 0 items] โโ 1 โ โญโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฎ โโ โ โ # โ content โ users โ โโ โ โโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โโ โ โ 0 โ THUMBS_UP โ โญโโโโโโโโโโโโโฌโโโโฎ โ โโ โ โ โ โ โ totalCount โ 1 โ โ โโ โ โ โ โ โฐโโโโโโโโโโโโโดโโโโฏ โ โโ โ โฐโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโฏ โโ 2 โ [list 0 items] โโ 3 โ [list 0 items] โโ 4 โ โญโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโฎ โโ โ โ # โ content โ users โ โโ โ โโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโค โโ โ โ 0 โ THUMBS_UP โ โญโโโโโโโโโโโโโฌโโโโฎ โ โโ โ โ โ โ โ totalCount โ 5 โ โ โโ โ โ โ โ โฐโโโโโโโโโโโโโดโโโโฏ โ โโ โ โฐโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโฏ โโฐโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏWe care about the total count.
We get that by accessing users.totalCount.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| insert thumbsUp { $in.reactionGroups | where content == THUMBS_UP | get users.totalCount}| get thumbsUp| first 5โญโโโโฌโโโโโโโโโโโโโโโโโฎโ 0 โ [list 0 items] โโ 1 โ โญโโโโฌโโโโฎ โโ โ โ 0 โ 1 โ โโ โ โฐโโโโดโโโโฏ โโ 2 โ [list 0 items] โโ 3 โ [list 0 items] โโ 4 โ โญโโโโฌโโโโฎ โโ โ โ 0 โ 5 โ โโ โ โฐโโโโดโโโโฏ โโฐโโโโดโโโโโโโโโโโโโโโโโฏSome rows now have empty lists, and some have lists containing a single entry: the number of ๐ reactions.
With get 0 we get the first element of a list.
By adding --optional, this command doesnโt fail on empty lists but returns null instead.
We replace null with 0, by running default 0.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| insert thumbsUp { $in.reactionGroups | where content == THUMBS_UP | get users.totalCount | get 0 --optional | default 0}| get thumbsUp| first 5โญโโโโฌโโโโฎโ 0 โ 0 โโ 1 โ 1 โโ 2 โ 0 โโ 3 โ 0 โโ 4 โ 5 โโฐโโโโดโโโโฏGet the Five Issues With the Most ๐ Reactions
Section titled โGet the Five Issues With the Most ๐ ReactionsโThe three columns we truly care about are thumbsUp, title and url, so letโs select those.
We also sort the table, so that the issues with the most ๐ reactions come first.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| insert thumbsUp { $in.reactionGroups | where content == THUMBS_UP | get users.totalCount | get 0 --optional | default 0}| select thumbsUp title url| sort-by --reverse thumbsUp| first 5โญโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎโ # โ thumbsUp โ title โ url โโโโโโผโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโคโ 0 โ 5 โ Proposal to allow the use of Pixi workspaces through a named registry of workspaces โ https://github.com/prefix-dev/pixi/issues/4461 โโ 1 โ 1 โ pixi-build: load variants from packages or files โ https://github.com/prefix-dev/pixi/issues/4429 โโ 2 โ 1 โ `pixi run echo '{{ hello }}'` fails โ https://github.com/prefix-dev/pixi/issues/4432 โโ 3 โ 1 โ Environment variable of tasks are broken when defined inside task โ https://github.com/prefix-dev/pixi/issues/4451 โโ 4 โ 1 โ Documentation: Add switchable pyproject.toml / pixi.toml code snippets โ https://github.com/prefix-dev/pixi/issues/4452 โโฐโโโโดโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏRename thumbsUp Column
Section titled โRename thumbsUp ColumnโUnicode can be a bit annoying to type in the terminal, but now itโs time to rename our thumbsUp column to ๐.
gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| insert thumbsUp { $in.reactionGroups | where content == THUMBS_UP | get users.totalCount | get 0 --optional | default 0}| select thumbsUp title url| sort-by --reverse thumbsUp| rename --column { thumbsUp: ๐ }| first 5โญโโโโฌโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎโ # โ ๐ โ title โ url โโโโโโผโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโคโ 0 โ 5 โ Proposal to allow the use of Pixi workspaces through a named registry of workspaces โ https://github.com/prefix-dev/pixi/issues/4461 โโ 1 โ 1 โ pixi-build: load variants from packages or files โ https://github.com/prefix-dev/pixi/issues/4429 โโ 2 โ 1 โ `pixi run echo '{{ hello }}'` fails โ https://github.com/prefix-dev/pixi/issues/4432 โโ 3 โ 1 โ Environment variable of tasks are broken when defined inside task โ https://github.com/prefix-dev/pixi/issues/4451 โโ 4 โ 1 โ Documentation: Add switchable pyproject.toml / pixi.toml code snippets โ https://github.com/prefix-dev/pixi/issues/4452 โโฐโโโโดโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏFormat Table in Markdown Format
Section titled โFormat Table in Markdown FormatโIn the end, we want to add this table to the body of a GitHub issue. Luckily, Nu has integrated support to convert its values to Markdown.
let top_issues_week = gh issue list --repo $repo --json createdAt,reactionGroups,title,url| from json| where ($it.createdAt | into datetime) >= (date now) - 1wk| insert thumbsUp { $in.reactionGroups | where content == THUMBS_UP | get users.totalCount | get 0 --optional | default 0}| select thumbsUp title url| sort-by --reverse thumbsUp| rename --column { thumbsUp: ๐ }| first 5| to mdWhat you can see here is the Markdown table directly embedded in this post, which is also written in Markdown.
| ๐ | title | url |
|---|---|---|
| 5 | Proposal to allow the use of Pixi workspaces through a named registry of workspaces | https://github.com/prefix-dev/pixi/issues/4461 |
| 1 | pixi-build: load variants from packages or files | https://github.com/prefix-dev/pixi/issues/4429 |
| 1 | pixi run echo '{{ hello }}' fails | https://github.com/prefix-dev/pixi/issues/4432 |
| 1 | Environment variable of tasks are broken when defined inside task | https://github.com/prefix-dev/pixi/issues/4451 |
| 1 | Documentation: Add switchable pyproject.toml / pixi.toml code snippets | https://github.com/prefix-dev/pixi/issues/4452 |
Create the Issue
Section titled โCreate the IssueโNow we can create an issue with the table we just generated.
gh issue create --title "Top issues last week" --body $top_issues_weekHow to update an existing issue is left as an exercise to the reader.
Conclusion
Section titled โConclusionโI hope I convinced you that scripting with Nushell can be a lot of fun. Itโs quick to type like bash, and has proper data types like Python.
With Nu, itโs easy to interact with your data: you extend your pipeline until you are happy with what it does.
Many thanks to Sabrina and Lucas for their comments and suggestions on this article
You can find the discussion at this Mastodon post.