DEV Community

Uthman Oladele
Uthman Oladele

Posted on

Stop Writing Bash Scripts, There's a Better Way

If you've ever written a Bash script longer than 30 lines, you know the feeling.
You come back to it a week later and have no idea what it does. Error handling is
a mess of $? checks, variables are global by default, and debugging feels like
archaeology.

I got tired of it. But I also didn't want to spin up a Python virtual environment
just to move some files around or hit an API. That felt like overkill.

So I built Logos.

What is Logos?

Logos is a small scripting language I wrote in Go. It is designed for the kind of
work Bash handles poorly: readable logic, proper error handling, built-in HTTP and
file operations, and code you can actually come back to a week later.

It is not trying to replace Python. It is not trying to replace Go. It is just a
tool for that middle ground where Bash becomes unreadable but pulling in a full
language feels like too much.

Scripts use the .lgs extension and you run them with the lgs command.

What does it look like?

Here is a simple HTTP request in Logos:

let res = httpGet("https://api.example.com/data")

if res.ok {
    let data = parseJson(res.value.body)
    print(data["message"])
} else {
    print("Error: " + res.error)
}
Enter fullscreen mode Exit fullscreen mode

No exceptions. No try/catch. Functions return a result table with ok, value,
and error fields. You check what you need and move on.

Compare that to doing the same thing in Bash. You are manually checking exit
codes, parsing curl output with awk, and hoping nothing breaks silently.

Why not just use Python?

Python is great. But for quick scripts, you are dealing with virtual environments,
import management, and a language that was not really designed for CLI work. It
also needs to be installed and configured on every machine you run it on.

Logos ships as a single binary. Install it and run your script. That is it.

Why not just use Go?

Go requires a compile step. If you are writing a quick script to back up some
files or hit an API, you do not want to set up a module and run go build every
time you make a change. Logos runs scripts directly, like a shell language should.

Also, Logos can be embedded inside Go applications as a scripting engine. You can
register Go functions, set variables, and run Logos scripts from within your Go
code. That is something Go itself cannot do cleanly.

vm := logos.NewWithConfig(logos.SandboxConfig{
    AllowFileIO:  false,
    AllowNetwork: false,
    AllowShell:   false,
    AllowExit:    false,
})

vm.Register("greet", func(args ...logos.Object) logos.Object {
    name := args[0].(*logos.String).Value
    return &logos.String{Value: "hello " + name}
})

vm.Run(`print(greet("world"))`)
Enter fullscreen mode Exit fullscreen mode

What can it do?

  • File I/O: read, write, copy, move, delete, glob
  • HTTP: GET, POST, PATCH, DELETE
  • JSON: parse and stringify
  • Concurrency: spawn blocks and spawn for-in loops
  • A formatter: lgs fmt yourfile.lgs
  • A compiler: lgs build yourfile.lgs compiles your script to a standalone binary
  • A REPL: just run lgs with no arguments
  • A standard library: math, string, array, path, time, logging, testing, and more

A real example

Here is a backup script written in Logos:

let source = trim(prompt("Source directory: "))

if !fileExists(source) {
    print("Error: " + source + " does not exist")
    exit(1)
}

let dest = trim(prompt("Backup destination: "))
let timestamp = replace(dateTimeStr(), " ", "_")
let backupPath = dest + "/backup_" + timestamp

let result = fileMkdir(backupPath)
if !result.ok {
    print("Failed to create backup directory")
    exit(1)
}

let files = fileReadDir(source)
for entry in files.value {
    fileCopy(source + "/" + entry, backupPath + "/" + entry)
}

print("Backup complete: " + backupPath)
Enter fullscreen mode Exit fullscreen mode

Clean. Readable. Easy to come back to.

How to install

curl -fsSL https://raw.githubusercontent.com/codetesla51/logos/main/install.sh | sh
Enter fullscreen mode Exit fullscreen mode

Works on Linux and macOS. Picks the right binary for your OS and architecture
automatically.

Try it

If you have feedback, run into bugs, or want to contribute examples or standard
library utilities, open an issue or a PR. The project is new and I am actively
working on it.

I built this because I wanted it to exist. Maybe you will find it useful too.

Top comments (0)