#!/usr/bin/tcc -run
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Hello from C!\n");
for (int i = 1; i < argc; ++i)
printf("argument %d: %s\n", i, argv[i]);
return 0;
}
And ready is your cscript :)
$ chmod u+x cscript && ./cscript hello world
Hello from C!
argument 1: hello
argument 2: world
(I can't even articulate why I love it so much that this works)
Obviously it's not a shell script, it's still C. It's fun though and being able to freely specify an interpreter/execution path using a shebang has led me to write some useful little command line utilities in unlikely programming languages over the years. That said, not sure why changing the working directory would be the litmus test. A C program can change its own working directory just as easily as an ordinarily executed bash script?
$ cat bscript.sh && echo "---" && ./bscript.sh
#!/usr/bin/bash
cd testdir/
ls
---
dummyfile
Well, you can "source" a script, so its effects persist in your current shell session. That's a feature of the script and your shell sharing the same language.
This looks great. We have a lot of bash tools because it's the only stable interpreter that we have readily available on all our systems. But bash is a pain to write so this might actually make things easier.
I had a small project that embedded the Lua interpreter in scripts as base64, which allowed me to write shell scripts in Lua, since it carried the interpreter with it. About 270k of bloat to make it work, though.
For small stuff I use bash / sed / awk / jq / yq / curl etc. I stopped using perl (a long time ago) and hate trying to build or distribute anything in Python. "You asked for a script! I give you... a venv, a pip install, woops need to compile something, so let's install build tools. Actually let's get github actions set up to handle this, or would you prefer a Docker image? Do you have a registry so I can share the image? Wait are you using a Mac? Multiarch image time! Or should I just give you a bag of scripts and a Dockerfile? Oh you're using Podman rootless, need you to read this page on how to access your own files as "you" in your container. Shit the wheels fell off! But look, Python is amazing and can do lots of stuff bash / curl / jq can't do!"
So these days I almost exclusively use Go wherever bash and friends aren't enough. Compile to Linux x86 & ARM and Darwin ARM, or just "go run" if it's simple enough.
You aren't really comparing apples to apples here. Anything you can do in bash/jq/curl you can do in python 3.x with only the stdlib. If you confine yourself to that, its still a better dev experience and can be run in any OS with a python package.
1. From the docs: "In the the project it is production ready because it is already used in this context because the shell code generated is tested and confirmed that works, the language is evolving with the tooling set."
Hmm...
2. Support Fish too. Having one language that can generate zsh (macOS default), Fish (power users default), and bash would be really nice!
The only thing I can think of is if you have an existing system you are integrating with thats implemented in shell script already - for example a packaging or build pack system; but I can’t really see how this could be justified even there because this could easily be a toy that becomes abandoned.
A really common use case is install/bootstrap/setup scripts. You know, those sketchy curl-to-bash things, or cloud-init scripts, or whatever you run to set up your actual higher level tools like Python.
So does an amber script after it's been compiled, that's the whole point. You can tweak it and inspect it if you want. Realistically though you'll probably regenerate it and copy the new compiled version over. But you can do both.
Is it? There is no example of what the compiled output looks like in the website or github. Just because its bash doesn't mean its suitable to be maintained in bash.
Because it's not preinstalled on every machine. Bash is a good target for portability reasons, but it's a shitty language to write in. If ever I get in the position again to have to write some bash, like for an installer or so, I'm going to be looking into Amber again.
Portability is dead now anyways. Something can have "sh" but all you can depend on are sh semantics and built ins. The whole point of a shell script is to compose a larger workflow out of the command line tools preinstalled on a system. I can't guarantee a sh script written on macOS is going to work on FreeBSD or Linux anyways, so there's zero reason to limit myself to sh.
Bash is great for orchestrating other Unix tools into an automated workflow. Only when that workflow requires stuff that Bash doesn't have is it time to break out Python. Integrate Shellcheck into your editor, and you get automated help for writing more reliable Bash.
ShellCheck is like a spaz hall monitor, filling my editor with useless warnings about what it believes are best practices. I thank my stars I mostly write shell scripts in zsh which it doesn't support.
Shellcheck has good heuristics, like making mistakes with for and subshell variables. I’ve never found its heuristics to be off-base, and when it can’t genuinely tell because of some context that is only known to you, you can opt out via # shellcheck disable=SCxxxx
Thank you, but... why not just write in Bash, or the shell you prefer? Why learn a yet another opinionated wrapper?
Yes, Bash or any shell is a very complex and utterly environment dependent language to approach with all due care for security and compatibility, yet hence the lack of wrapper that may not even be aware of these crucial cases at all.
There are other communities where movement in the language came from outside tooling that built extensions on top of the language, such as Sass or TypeScript.
It always comes to be a social problem. Sort of. I want to use X instead of Y, but maybe everyone does not want the same, or adaption of X is harder in technology wise. So I use wrapper Z that compiles to Y, and avoid some problems, but bring new problems. Maybe these problems are smaller ones than just keeping to use Y directly.
bash is really painful to use for anything beyond the most rudimentary logic. Bourne and Mashey were terrible language designers. (By contrast, Thompson's V6 shell is very elegant, if limited.)
That said, this should just be a shell itself and not something that generates into other shell dialects. Otherwise, why not use Ruby or something like it that has actual expressive power?
> That said, this should just be a shell itself and not something that generates into other shell dialects. Otherwise, why not use Ruby or something like it that has actual expressive power?
I'm guessing the advantage here would be that the compiled "bytecode" (the resulting bash) can be distributed to systems that would then not need to have Amber installed. (And vs. a real binary from, e.g., Go/Rust/etc., it isn't tied to the platform, either.)
Vs. a Ruby script would require Ruby as a run-time dependency; Amber here is effectively a compile-time dependency.
Python 3 is available basically everywhere these days though, so I think there's still a lot of merit to just using a higher level language like you suggest. Even Ruby, while not available out of the box, is not exactly hard to get on most OSes.
Do we really want to stop evolving the space of languages (and libraries and frameworks while we're at it) just because we have LLM's writing code now? If LLM's were truly smart, they'd argue with us that we should stop asking them to write bash code, because it's a shitty error-prone language. True intelligence should be skeptical of itself and not take any request as a requirement.
I tried this or something similar a while ago and really wanted a better argument parsing experience
https://docs.amber-lang.com/0.6.0-alpha/basic_syntax/importi...
it seems like automatic `--help` + named args is still not a thing? if it were, I'd be all over this
Any language is a shell script if you're brave enough: https://en.wikipedia.org/wiki/Shebang_%28Unix%29
Exactly
And ready is your cscript :) (I can't even articulate why I love it so much that this works)Can you change the current working directory? If not, it's not a shell script.
Obviously it's not a shell script, it's still C. It's fun though and being able to freely specify an interpreter/execution path using a shebang has led me to write some useful little command line utilities in unlikely programming languages over the years. That said, not sure why changing the working directory would be the litmus test. A C program can change its own working directory just as easily as an ordinarily executed bash script?
in C you can change dir easily via `chdir()`[1] [1] https://www.man7.org/linux/man-pages/man2/chdir.2.htmlIf you meant somehow changing the parent shell's directory an ordinary bash script doesn't do that either
Presumably you can call chdir(2) from the C code?
Or did you mean change the directory of the calling shell (in which case, executable shell scripts written in Bash and friends can’t do that either).
Well, you can "source" a script, so its effects persist in your current shell session. That's a feature of the script and your shell sharing the same language.
Sure, but “shell scripts” as an (admittedly imprecise) term usually imply separate executable files, not shell libraries/functions that are sourced.
Then it seems that what you want is running a repl of your chosen language rather than shell/"executable" scripts.
Of course you can. How do you think `cd` utility is implemented?
cd is a shell built-in, not a script.
Can go one step further and define a custom binfmt like was done here https://blog.cloudflare.com/using-go-as-a-scripting-language...
Didn't know about the binfmt_misc hooks in Linux. Good read! Thanks for sharing.
This looks great. We have a lot of bash tools because it's the only stable interpreter that we have readily available on all our systems. But bash is a pain to write so this might actually make things easier.
I had a small project that embedded the Lua interpreter in scripts as base64, which allowed me to write shell scripts in Lua, since it carried the interpreter with it. About 270k of bloat to make it work, though.
How many places do you have Bash, but not AWK?
Or Perl. Or Python. How many environments have only bash and not awk, perl, or python?
For small stuff I use bash / sed / awk / jq / yq / curl etc. I stopped using perl (a long time ago) and hate trying to build or distribute anything in Python. "You asked for a script! I give you... a venv, a pip install, woops need to compile something, so let's install build tools. Actually let's get github actions set up to handle this, or would you prefer a Docker image? Do you have a registry so I can share the image? Wait are you using a Mac? Multiarch image time! Or should I just give you a bag of scripts and a Dockerfile? Oh you're using Podman rootless, need you to read this page on how to access your own files as "you" in your container. Shit the wheels fell off! But look, Python is amazing and can do lots of stuff bash / curl / jq can't do!"
So these days I almost exclusively use Go wherever bash and friends aren't enough. Compile to Linux x86 & ARM and Darwin ARM, or just "go run" if it's simple enough.
You aren't really comparing apples to apples here. Anything you can do in bash/jq/curl you can do in python 3.x with only the stdlib. If you confine yourself to that, its still a better dev experience and can be run in any OS with a python package.
I highly recommend UV If you find yourself forced to use python, UV is the way to go
Try it out :)
uv init uv add XXX uv run main.py
( You can pin python versions and auto install them etc )
Just wanted to say that I think you did a great job with your examples showing why someone might be interested in this language.
1. From the docs: "In the the project it is production ready because it is already used in this context because the shell code generated is tested and confirmed that works, the language is evolving with the tooling set."
Hmm...
2. Support Fish too. Having one language that can generate zsh (macOS default), Fish (power users default), and bash would be really nice!
unclear use case imo - this sacrifices the ergonomics of actual bash scripting, and hides it behind another language
If your script is complex enough to need a higher level language you might as well just switch to python
The only thing I can think of is if you have an existing system you are integrating with thats implemented in shell script already - for example a packaging or build pack system; but I can’t really see how this could be justified even there because this could easily be a toy that becomes abandoned.
A really common use case is install/bootstrap/setup scripts. You know, those sketchy curl-to-bash things, or cloud-init scripts, or whatever you run to set up your actual higher level tools like Python.
bash scripting has ergonomics?
Regardless of where it’s deployed I can edit it and run it without any additional tools.
So does an amber script after it's been compiled, that's the whole point. You can tweak it and inspect it if you want. Realistically though you'll probably regenerate it and copy the new compiled version over. But you can do both.
Is it? There is no example of what the compiled output looks like in the website or github. Just because its bash doesn't mean its suitable to be maintained in bash.
Yes?
How does it achieve memory safety? Via garbage collection? Via runtime checks? Via some clever compile-time analysis?
I’ll give it a shot.
Side note: the image of project founder cosplaying as Steve Jobs on front page had me dying.
I clicked the link to see this image and wasn't disappointed. It's fantastic!
Much needed. I have hard time understanding bash.
It’s not like you have to anymore. If you are going to take on a dependency to generate bash for you, why would it not be a coding agent?
Hm... But why not use Python
Because it's not preinstalled on every machine. Bash is a good target for portability reasons, but it's a shitty language to write in. If ever I get in the position again to have to write some bash, like for an installer or so, I'm going to be looking into Amber again.
portability but not posix shell? tsk tsk
Portability is dead now anyways. Something can have "sh" but all you can depend on are sh semantics and built ins. The whole point of a shell script is to compose a larger workflow out of the command line tools preinstalled on a system. I can't guarantee a sh script written on macOS is going to work on FreeBSD or Linux anyways, so there's zero reason to limit myself to sh.
First of it's not compiled, it's transpiled
Second, just why?
I'm a fan of this project. Great work!
> Typescript to bash
Literally the worst of both worlds.
Bash is great for orchestrating other Unix tools into an automated workflow. Only when that workflow requires stuff that Bash doesn't have is it time to break out Python. Integrate Shellcheck into your editor, and you get automated help for writing more reliable Bash.
ShellCheck is like a spaz hall monitor, filling my editor with useless warnings about what it believes are best practices. I thank my stars I mostly write shell scripts in zsh which it doesn't support.
Shellcheck has good heuristics, like making mistakes with for and subshell variables. I’ve never found its heuristics to be off-base, and when it can’t genuinely tell because of some context that is only known to you, you can opt out via # shellcheck disable=SCxxxx
It does have some "false positives" but by and large I find it helpful. I never saw a script misbehave where I followed Shellcheck's advice.
Great compared to what? It was great in the ‘90s, not today.
bash bashing i can understand. whats wrong with ts tho?
Everything, when other options are available? The strongest argument for Typescript is that it isn’t JavaScript, which doesn’t apply here.
Everything related to JavaScript is terrible.
Another alternative for writing Bash is Babashka, which is a Clojure dialect.
Thank you, but... why not just write in Bash, or the shell you prefer? Why learn a yet another opinionated wrapper?
Yes, Bash or any shell is a very complex and utterly environment dependent language to approach with all due care for security and compatibility, yet hence the lack of wrapper that may not even be aware of these crucial cases at all.
Your argument is down to the weights.
There are other communities where movement in the language came from outside tooling that built extensions on top of the language, such as Sass or TypeScript.
It always comes to be a social problem. Sort of. I want to use X instead of Y, but maybe everyone does not want the same, or adaption of X is harder in technology wise. So I use wrapper Z that compiles to Y, and avoid some problems, but bring new problems. Maybe these problems are smaller ones than just keeping to use Y directly.
bash is really painful to use for anything beyond the most rudimentary logic. Bourne and Mashey were terrible language designers. (By contrast, Thompson's V6 shell is very elegant, if limited.)
That said, this should just be a shell itself and not something that generates into other shell dialects. Otherwise, why not use Ruby or something like it that has actual expressive power?
> That said, this should just be a shell itself and not something that generates into other shell dialects. Otherwise, why not use Ruby or something like it that has actual expressive power?
I'm guessing the advantage here would be that the compiled "bytecode" (the resulting bash) can be distributed to systems that would then not need to have Amber installed. (And vs. a real binary from, e.g., Go/Rust/etc., it isn't tied to the platform, either.)
Vs. a Ruby script would require Ruby as a run-time dependency; Amber here is effectively a compile-time dependency.
Python 3 is available basically everywhere these days though, so I think there's still a lot of merit to just using a higher level language like you suggest. Even Ruby, while not available out of the box, is not exactly hard to get on most OSes.
Hot take, but Powershell is quite an elegant shell language. It's actually a lot easier to write than Bash.
It took my quite a while to get used to all the verbose method names, but it actually makes it pretty readable by default.
If you don't want to use it, don't use it
In a world where AI can generate any code for any environment, is there a need for another language?
On the other hand, we're at a point for a binary language (or standard / framework) that one AI/LLM creates and another one validates.
What are we missing?
Do we really want to stop evolving the space of languages (and libraries and frameworks while we're at it) just because we have LLM's writing code now? If LLM's were truly smart, they'd argue with us that we should stop asking them to write bash code, because it's a shitty error-prone language. True intelligence should be skeptical of itself and not take any request as a requirement.
Agreed, not our choice but isn't that the reality now?
> is there a need for another language?
If you know of a language that is perfect for all our needs today and tomorrow, please guide us to it.
> What are we missing?
Major concerns would be i) trust in the tooling, ii) quality and accountability, iii) future investment in competent engineering.
True, There isn't one, there will be never one. Isn't that how we end up so many and it never ends.
We're missing AI that doesn't still its hand held every step of the way.
You guys can stop down voting.
This is not something we're advocating, instead talking the reality from observing across the industry.
I wonder what notable thing has the "industry" produced during your observation (apart from more JIRA tickets).