nushell for SAP Developers
If you like working in the terminal and work in an SAP environment - this article might encourage you to try out Nushell, "a new type of shell" as its creators and contributors describe it. The examples shown here are based on SAP-related tools as I work with them a lot, hence the title. But if you don't work in SAP areas - I still encourage you to see what nushell can do.
If you don't like working in the terminal, this article might motivate you to see if a shell is for you.
Okay, so why Nushell?
First — I don’t really like Bash. I’ve learned some of it, but without much enthusiasm (or memory) for the commands and their syntax. I know: containers, it’s the default, it’s widely used. But these days I can throw whatever I need into an LLM and be done. For day-to-day work — nope.
Second — since I work on Windows daily — cmd is too simple, and I only had a short stint with PowerShell.
Third — for some time now I’ve preferred the terminal, commands, and keyboard-driven workflows.
And with Nushell I can do a lot. Once I discovered and tested it, I stuck with it
for good for my daily blood, sweat and tears work.
Why?
Readable commands and syntax, a rich type system where almost everything is data, and native support for many formats. I’ll show a few capabilities I use in my work with SAP solutions.
Wyjście z komend Cloud Foundry
I often check the status of services or applications in SAP BTP Cloud Foundry.
cf services or cf apps.
When I use an extra, smaller pane in Windows Terminal, the output looks roughly like this:
Drama.
Nushell treats the output of its own commands (e.g., ls) as data, not just a
string of characters. It can handle the output of external commands the same way.
Since the output of cf services looks like a table, let’s indicate we want a table:
cf services | detect columns --guess --skip 2 | select name offering "last operation"
We pipe the output of cf services (|) into detect columns with extra parameters - let
Nushell try to infer the layout and skip the first two lines, where cf services
prints Getting service instances... followed by a blank line.
Then we pass the result of column detection through a column selection - we only
want the name, the service type (offering), and the last operation:
Much better. The services are sorted by name; a different ordering might be preferable, for example by type (offering).
cf services | detect columns --guess --skip 2 | select name offering "last operation"
| sort-by offering
If I needed to turn this into JSON and save it to a file:
cf services | detect columns --guess --skip 2 | select name offering "last operation"
| sort-by offering | to json o> services.json
If there are many services, add explore to browse them with arrow keys:
The output of cf apps doesn’t look that bad in a small pane, but I want to hide
routes and processes and list only stopped apps:
cf apps | detect columns --guess --skip 2 | where requested == stopped | select name
This time we use where, which lets us query the data!
What if I want only apps that have sample in the name?
cf apps | detect columns --guess --skip 2 | where requested == stopped
| where name =~ "sample" | select name
BTW, Nushell’s readability is an advantage for me, but I understand for some it might be something bad. Too long? If I’m using them again, I use Ctrl+r and start typing.
I also have a config file with aliases and custom commands - because more complex commands can’t be aliases. So if I use something very often, it ends up in that file as:
def cfs [] { cf services | detect columns --guess --skip 2
| select name offering "last operation" | sort-by offering }
And then it’s just cfs.
SAP CAP with SQLite…
When working with a SAP CAP project and using SQLite, you can, for example, use VSCode plugins or the SQLite CLI.
Or use Nushell, which has built-in support for SQLite. Let’s assume I deployed the project’s bookshop database to db.sqlite.
I can then do something like this:
open db.sqlite | explore
and navigate through tables and records.
Or immediately fetch the titles of books whose description contains “poem”:
open db.sqlite | get sap_capire_bookshop_books | where descr =~ "poem" | select title
…and OData
Now we've started our project; it's running at localhost:4004.
You can open a browser, Postman, or another REST client to check whether
our Books contains a book with "Raven" in the title — or stay in nushell and:
http get http://localhost:4004/admin/Books | get value | select title ID
| where title =~ Raven
Have you noticed that I’m not using OData syntax? It’s simply that from
what get … returns, nushell takes the value and that is structured data
for it — we select the title and ID columns and filter by title containing “Raven”.
Let’s add a new book; I defined the body earlier in the file test/sample.json:
{
"ID": 3,
"title": "Poems : Pocket Poets",
"descr": "The Everyman's Library Pocket Poets hardcover series is popular for its compact size and reasonable price which does not compromise content.",
"author": { "ID": 101 },
"genre": { "ID": 12 },
"stock": 5,
"price": "12.05",
"currency": { "code": "USD" }
}
open --raw test/sample.json | http post --content-type application/json
http://localhost:4004/admin/Books
The response...
http get http://localhost:4004/admin/Books | get value | select title ID
| where title =~ Pocket
...and the entry.
Browsing files
I'm still in my SAP CAP project. Do I have @sap/xsenv in the dependencies in
package.json? What do I have there at all? I know I can open the file in an editor,
but in many cases I prefer the terminal — I start typing and the shell
suggests the rest. Witth ctrl + arrow I move through suggestions.
It's faster and more efficient for me than opening the file.
open package.json | get dependencies
And in mta.yaml - do I have HANA db in resources?
open mta.yaml | get resources
OK, it's there.
As you can see, Nushell can work with JSON and YAML. open reads those files,
parses them into typed data, and from then on we can use Nushell commands
to fetch, query, display, etc.
If you want the file as a string:
open --raw mta.yaml
If you're accustomed to cat, you can set up an alias:
alias cat = open --raw
What about CSV?
Yes — if you have test files with CSV data, Nushell works with them too:
open db\data\sap.capire.bookshop-Authors.csv
This means exactly the same as with JSON, YAML, XML, and SQLite — you can use the same commands to query them:
open db\data\sap.capire.bookshop-Authors.csv | where name =~ "Emily" | select ID name
What about command completion?
Nushell has various plugins and additional scripts for command autocompletion - for example, for Git.
git switch and next tab:
With the help of LLMs, I also generated completions for CLIs used in SAP projects: the BTP CLI, CAP (cds) CLI, Cloud Foundry CLI, and UI5 CLI.
Installation instructions for these completions are available on the official repository page with various completions and scripts.
Nicer prompt
Nushell works with oh-my-posh. Additionally, my prompt shows the currently logged Cloud Foundry org/space. This and other segments I created are described in the another blog post.
These are just a few things I like about Nushell. Of course things like auto-complete etc. it's notsomething other fancy shells don't have, but in the combination with the structured output it did the job for me. I'm still discovering it, and with each discovery I like it even more.