Expand

syshell

sy·shell is a system shell designed as an alternative to bash, fish, or nushell.

Why?

Language:

Runtime:

More detailed comparison available here.

Why not?

It's in alpha and it's not fully implemented, e.g. no YAML, no Windows. The focus is to get the language and runtime right, then focus on the interactive shell and standard library.

How to Get It?

It is currently in a closed alpha. Fill out the form, if you want to try it out.

Examples

Release Script

:= declares a new variable
$tag := git describe --tags --abbrev=0
the end of the tar command is determined by indent
tar -czv
    -f "release-$tag.tar.gz"
    --exclude "*.o"
    --exclude "*.so"
    src/

Disk Space Check

$threshold   := 0.8
$targetMount := "/"
discard the first line of the df output, set the second line to $line _, $line := df -k $targetMount
split the line using :columns formatter, which splits by spaces awk-style $stat := $line:columns
:int converts a string to an integer
$used, $total := $stat[2]:int, $stat[1]:int
use any expressions inside {} in strings
if $used/$total > $threshold {
    $toFree := $used - $total*$threshold

    print "$targetMount usage is too high"
    print "Target is {$threshold * 100}%"
    print "Please free $toFree KB"
    exit 1
} else {
    print OK
}

:columns, :int and :json are called formatters, they parse a string from a specified format to a syshell type. There are lots of built-in formatters that cover many scripting needs.

Send a Slack Message

$token := "xx-secret-token-yy"
$channelID := "C123"
$msg := "test message"

$payload := {
    channel: $channelID,
    text:    $msg,
}
@json is also a formatter, but it's doing reverse of :json. $payload@json convert a syshell object (a map in this case) to a JSON string.
$response := curl -s -X POST
    -H "Authorization: Bearer $token"
    -H "Content-Type: application/json"
    -d $payload@json
    https://slack.com/api/chat.postMessage
  | from json
panic stops current function and starts propagating an error. If no one handles this error, syshell will print it along with a stack trace.
if !$response.ok {
    # when "ok" is false, slack response
    # must contain an "error" field
    panic "slack error:" $response.error
}

@json are @csv are also formatters, @json converts from a syshell type to a string in a specified format, @json is a reverse of :json. Formatters always come in pairs.

Indent a File

for processess input line-by-line
cat a-file.txt
    | for $line { print "  $line" }

syshell works with external program's output as if they were a stream of lines.

Wait for an Event

Same as cat, just interactive. tail -f access.log
in works like in python.
| for $req {
    if "/honeypot" in $req {
      break
    }
}

for consumes items or lines as they come, once there's a line with "/honeypot" inside, break will stop to the loop, and tail -f will quit.

Countries Stats

Given a CSV file with cities stats like below, compute how many 1M+ population cities each country has:

>> head -4 cities.csv
"city","lat","lng","country","iso2","population"
"Tokyo","35.6897","139.6922","Japan","JP","37732000"
"Jakarta","-6.1750","106.8275","Indonesia","ID","33756000"
"Delhi","28.6100","77.2300","India","IN","32226000"
$countries := {}
For each CSV record, create a map and send it over a pipe to a for loop.
from csv < cities.csv
  | for $city { 
      if $city.population:float > 1000000 { 
        $countries[$city.country] += 1
      }
  }
put $countries

Pipes in syshell can transport typed values without serialization overhead.

Disk Space Check Function

Function check-space must have exactly one argument, which will be assigned to $mount.
fn check-space $mount {
    _, $line := df -k $mount
    $stat := $line:columns
    $used, $total := $stat[2]:int, $stat[1]:int
put adds typed value to the output stream.
put ($used / $total > 0.8)
put ($total - $used)
}
$rootOK is a boolean, $left is an integer. $rootOK, $left := check-space /

put adds its arguments to the output stream as is, while print converts arguments to strings and may output multiple lines, if arguments have \n in them.

Build Function

# build source files into executables and
# shared libraries
fn build
List function options and they will be set to specified variables
-C           $directory
-t|--target  $arch
-o|--output  $destination
Validate that supplied parameters have a correct type
-j|--jobs    (int)$jobs
-v|--verbose (bool)$verbose
-f|--force   (bool)$forceRebuild
$name
{
    # implementation
}

Next Step

Read a language intro.