## 1. Project Overview & Quickstart (amber-lang/amber)

[](https://www.gnu.org/licenses/lgpl-3.0)    [](https://deepwiki.com/amber-lang/amber)



# Amber

Programming language that compiles to Bash. It's a high level programming language that makes it easy to create shell scripts. It's particularly well suited for cloud services.

> [!Warning]
> This software is not ready for extended usage.

[Join our Discord](https://discord.com/invite/cjHjxbsDvZ) or
#amber-lang on irc.oftc.net (irc://irc.oftc.net/#amber-lang) or
[Join our Matrix room](https://matrix.to/#/#_oftc_#amber-lang:matrix.org)

## Install

You can find an installation guide on the [documentation website](https://docs.amber-lang.com/getting_started/installation).

## Contributing

Contributing guide can be found on the [documentation website](https://docs.amber-lang.com/contribute/contribute).

## 2. Official Technical Reference & Guides (amber-lang/amber-docs)

## File: README.md

<h1> Official documentation of Amber </h1> 

## What is Amber?

[Amber](https://amber-lang.com/) is a cutting-edge programming language compiled into Bash Script. With a focus on modern syntax, safety features, type safety, and practical functionalities that exceed the capabilities of Bash, Amber aims to provide a streamlined and robust scripting experience. The implementation is written in Rust and hosted [on GitHub](https://github.com/amber-lang/amber).

### Documentation Purpose

This documentation serves as a comprehensive guide to understanding and utilizing the features of Amber. Whether you are a seasoned developer or a newcomer, this documentation will walk you through the unique aspects and advantages that Amber brings to the world of scripting.

Explore the sections [here](https://docs.amber-lang.com/) to delve into Amber's syntax, safety measures, and practical functionalities, and discover how it can enhance your scripting workflow. If you have any questions or need assistance, feel free to reach out for support.

Happy scripting with Amber!

## Installation

```sh
# Install dependencies
npm install
# Generate the stdlib documentation
./sync-stdlib-doc.ab
# Start the development server
npm run dev
```

---

## File: docs/nightly-alpha/getting_started/faq.md

# FAQ

## Who is Amber for?

Amber is aimed at developers who need the power of a modern programming language while staying within the ubiquitous Bash environment. It is especially useful for:
- System administrators automating complex tasks.
- DevOps engineers writing portable scripts.
- Developers who want type‑safety and richer abstractions without abandoning the shell.

## Why not Python?

Python excels at many domains, but it requires a separate runtime and often incurs additional deployment overhead. Amber compiles directly to Bash, so you can:
- Leverage existing shell tooling and pipelines.
- Deploy a single script without installing a language interpreter.
- Benefit from Bash‑native features (process substitution, job control) while enjoying high‑level syntax and safety.

## Why not write Bash directly?

Pure Bash scripts lack static type checking, modular imports, and modern language constructs. Amber provides:
- A type system that catches errors early.
- Structured imports and modules for better code organization.
- Built‑in helpers (e.g., safe string interpolation, automatic error handling) that reduce boilerplate.

## How does Amber compare to other languages?

| Feature | Amber | Bash | Python | 
|---|---|---|---|
| Compiles to Bash | ✅ | ✅ | ❌ | 
| Static typing | ✅ | ❌ | ✅ |
| Native shell integration | ✅ | ✅ | ❌ |
| Learning curve | Low | Moderate | Moderate |

Amber fills a niche between lightweight shell scripting and full‑featured high‑level languages.

## Is Amber production‑ready?

Amber is under active development. The **nightly** provides the latest features and improvements, but may contain breaking changes.  
For production workloads, we recommend using the latest stable release (e.g., `0.5.x`) rather than the nightly build.

In the the project it is production ready because it is already used in this context because the Bash code generated is tested and confirmed that works, the language is evolving with the tooling set.

## Can I use Amber for system scripts?

Yes. Amber is designed for exactly that purpose. It can replace many typical Bash one‑liners and larger maintenance scripts, offering better readability, safety, and testability while still running on any POSIX‑compatible system.

## What shells does Amber support?

Currently, Amber targets **Bash** versions 3.2 through 5.3. We actively test across:
- Linux (GNU bash 3.2-5.3)
- macOS (bash 3.2)

The compiled code is highly portable and will run on any system with the target shell installed.

## Can Amber compile to other shells like Zsh or POSIX sh?

Yes, this is actively being developed. Amber currently targets Bash as its primary shell, but we're working on mechanisms to allow targeting different shells. For now, you can use Amber's built-in features that have equivalents in POSIX shell, and we're working on a target configuration that will let you specify the target shell.

## Why not just use an LLM to write scripts?

LLMs can generate scripts, but they come with their own challenges:
- Scripts may only work on your machine with your specific Bash version
- No type safety or compile-time error checking
- Security concerns with AI-generated code

Amber provides the ease of writing with a modern syntax while ensuring your scripts work reliably across different environments.

## Is Amber better than Python for shell tasks?

It depends on your needs:

| Consider Amber if... | Consider Python if... |
|---------------------|----------------------|
| You need maximum portability (only Bash required) | You need external dependencies (pip packages) |
| Your scripts should run on any Unix-like system | You control the strict deployment environment |
| You want type safety in shell scripting | You need complex data structures or pip dependencies |
| You prefer Bash-native features | You need complex APIs or specific integration with other technologies |

Many users use Amber for system administration and DevOps tasks where portability matters, and Python for application development where ecosystem matters more.

## Can I use Amber for CI/CD pipelines?

Absolutely! Amber shines in CI/CD because:
- Only Bash is required (pre-installed on all CI runners)
- Type safety catches errors before they reach production
- Scripts compile to clean, readable Bash
- *Bshchk* validation ensures dependencies exist
- The compiler itself can be installed via various methods (bin, brew, pip, etc.)

We even use Amber to generate parts of our own documentation!

## How does Amber handle error cases?

Amber enforces explicit error handling at compile time. If a function can fail, Amber will not compile your code unless you handle both success and failure cases, either by displaying an error message or failing silently. This prevents the "silent failure" problem common in Bash scripts where commands fail but execution continues as if nothing happened.

## Can Amber generate Bash that ShellCheck would accept?

Yes! Our focus on clean Bash generation means the compiled code follows ShellCheck (not yet at 100%) best practices. We're also working on integrating ShellCheck into our CI pipeline to ensure the generated code maintain high quality standards.

## Is Amber suitable for beginners?

Yes, Amber is designed to be approachable:
- Syntax similar to JavaScript/Python/Rust (familiar to most developers)
- Type system catches common mistakes early
- Built-in functions reduce boilerplate
- Documentation includes many examples
- The compiler provides helpful error messages

Many users start with Amber to learn scripting concepts before moving to more complex languages.

## Why was Amber created?

The project started as a PhD research topic, focusing on making Bash scripting safer and more maintainable. It gained community interest and evolved into a full project.

---

## File: docs/nightly-alpha/getting_started/getting_started.md

Welcome to the documentation of Amber the programming language! 🎉

Here is a minimal hello world example:
```ab
echo("Hello world!")
```

## What is Amber?

Amber is a programming language compiled into Bash Script. It was designed with a modern syntax, safety features, type safety and practical functionalities that Bash could not offer. The subsequent section will demonstrate how Amber embodies these characteristics.

### Modern Syntax

Amber is designed based on the ECMA script syntax. The goal was to create a syntax that any developer could feel comfortable with. Hence, Amber draws on features from languages like Rust and Python.

### Safety Features

When Bash command fails - it carries on with the code execution as if nothing has happened. This could lead to some serious problems and side effects that are irreversible.

We dislike this behavior. This is why Amber will not compile if edge cases aren't handled - whether that involves displaying an error message to the user or failing silently.

### Type Safety

Amber comes with a straightforward type system that aids in identifying simple bugs and errors at compile time, yet it remains unobtrusive, allowing you to focus on what matters most in scripting: the logic.

### Extra Features

Amber supports things that are essential to developer like floating point arithmetic, a non-obscure way to handle arrays or even passing variables by reference instead of by copy. In addition to that Amber comes with a standard library that includes features like text trimming, summing all number in an array, splitting text and many more.

### Supported Environments

Amber's compiled Bash scripts are actively tested across a range of environments.

| Environment       | Version Range | Status               | Notes                                                              |
|-------------------|---------------|----------------------|--------------------------------------------------------------------|
| **Bash (Linux) GNU**  | 3.2 - 5.3     | Under Testing | All versions within this range are tested using [tianon/docker-bash](https://github.com/tianon/docker-bash). |
| **Bash (macOS)**  | 3.2           | Under Testing | Verified through GitHub Actions `macos-latest` environments.       |
| **Bash (Linux) Busy Box**           | Latest           | Under Testing | Busy box environment. As of right now latest is 5.3 |

---

If you're wondering who Amber is for or why to use it instead of other languages, check the [FAQ](getting_started/faq).

---

## File: docs/nightly-alpha/getting_started/installation.md

## Installation

### Support for architectures

The Amber compiler currently works on:
- Linux x86 and ARM
- macOS x86 and ARM (Apple Silicon)
- Windows over WSL 2

### Preparation for installation

## macOS
On macOS, you should have everything preinstalled (curl, bash, bc).

## Linux
Make sure that the operating system meets the following prerequisites
- Install the basic calculator:
  - On Debian and Ubuntu: `sudo apt install bc` 
  - On Arch: `sudo pacman -Syu bc`
  - On Fedora: `sudo dnf install bc`
  - On OpenSUSE: `sudo zypper install bc`
  
- `curl` and `bash` are both installed by default in most cases. 
  In the very rare case that they happen to be not available yet, download them as well.

> DETAILS: You should always update the system before you install a package in a rolling release distro, such as **Arch** and **Tumbleweed.**  Always reboot after an update of the kernel, init system, and similar software as well. 

## Installation with Homebrew

Running this snippet will install latest stable version.

```sh
brew install amber-lang/amber/amber-lang
```

## Installation via `bin`, the binary package manager

**Install bin itself**:

Download the binary for your platform here:

```
https://github.com/marcosnils/bin/releases 
```

And then make it executable: 

```
chmod +x ./bin_0.24.2_linux_amd64
```

And now run it from the directory where it is located:

```
./bin_0.24.2_linux_amd64 install github.com/marcosnils/bin
```

And now, install Amber:

```
bin install github.com/amber-lang/amber
```

Update it via:

```
bin update
```

> DETAILS: Bin can install all binaries that are hosted somewhere on GitHub, Codeberg, and other locations. For detailed documentation, see: [Commands Reference](https://github.com/marcosnils/bin?tab=readme-ov-file#-commands-reference)

## Installation via script

- **System-wide**
```bash
bash <(curl -sL "https://github.com/amber-lang/amber/releases/download/0.5.1-alpha/install.sh")
```
- **Local-user**
```bash
bash -- <(curl -sL "https://github.com/amber-lang/amber/releases/download/0.5.1-alpha/install.sh") --user
```

- **Available versions with package managers**


[](https://repology.org/project/amber-lang/versions)


### NixOS Channel

The name of the package is `amber-lang`.
- **configuration.nix**
```nix
  environment.systemPackages = [
    pkgs.amber-lang
  ];
```
- **And with home manager:**
```nix
  home.packages = with pkgs; [
    amber-lang
  ];
  programs.home-manager.enable = true;
```

- **Start a shell with:**

```nix
nix-shell -p amber-lang
```

### NixOS with Flakes

- **You can use the Amber flake like this:**

```nix
{
    inputs = {
        # ...
        amber.url = "github:amber-lang/Amber";
    };
}
```

- **Flakes with home manager:**

```nix
home.packages = [ inputs.amber.packages.${pkgs.system}.default ];
```
While developing with Nix, the flake defines all dependencies for `nix develop` (or `direnv` if used).

### Snap

```bash
sudo snap install amber-bash --classic
```

## Windows Support

As Windows does not come with bash installed, it makes no sense to support it.  
Please install WSL 2 on your Windows machine and install the Linux version of the Amber compiler inside.

For it to work, you may need to run the following code that pulls all the prerequisites.  
These count for Debian and Ubuntu-based images.

```sh
sudo apt install curl bc
sudo mkdir /opt /usr/local/bin
```

## Integration of external tools

Amber is currently an alpha-stage project, and to implement some features, we have chosen to integrate external tools.  
If these tools are available on your system, they will be executed at the end of the Bash compilation process.

* [bshchk](https://github.com/b1ek/bshchk): A runtime Bash dependency checker. Install it separately on your system to enable automatic checking of external command dependencies in your compiled scripts. See the [bshchk repository](https://github.com/b1ek/bshchk) for installation instructions.

> [!TIP]
> bshchk is not included with Amber. For more information about using it, including inline directives and disabling it when needed, see the [Postprocessors section in the Usage guide](getting_started/usage#postprocessors).

## Uninstallation

If you have installed it via the script installation option, simply run the following code snippet.

```sh
bash -- <(curl -sL "https://github.com/amber-lang/amber/releases/download/0.5.1-alpha/uninstall.sh")
```

---

## File: docs/nightly-alpha/getting_started/migration_guide.md

This guide provides a step-by-step walkthrough for migrating code from 0.4.0-alpha to 0.5.0-alpha. The current version introduces several breaking changes. This document outlines the modifications, explains how to adapt your code to maintain the same behavior, and highlights updated features. In this guide we will cover two main categories of changes:
1. **Language Features**: Changes and updates to the core language syntax and semantics.
2. **Standard Library Updates**: Modifications to existing standard library functions and their usage.

Follow along to ensure a smooth transition to the new version. Let’s get started!

# New integer `Int` data type 

Previously, Amber supported only the `Num` type. This release introduces `Int`, which maps to Bash’s native integer arithmetic. To support this, we’ve updated parts of the language syntax.

## Array subscript

Expression in the subscript can only be of type `Int`.

```ab
// Before
arr[12.0] // Ok; although fails

// After
arr[12.0] // Error: array subscript can only be an integer
```

## Range

Expressions in range operator can only be of type `Int`.

```ab
// Before
10.0..15.0 // OK; although fails

// After
10.0..15.0 // Error: range can only be applied on integers
```

## Iterator

Iterator variable in for-loop is now of type `Int`.

```ab
// Before
for i, item in items {} // `i` is a `Num`

// After
for i, item in items {} // `i` is an `Int`
```

## Exit

Exit builtin now accepts only expressions of type `Int`.

```ab
// Before
exit 2.0 // Ok; although fails

// After
exit 2.0 // Error: exit accepts only `Int` type
```

## Status

The `status` builtin now returns a value of type `Int`.

```ab
// Before
status // Returns `Num` value

// After
status // Returns `Int` value
```

## Len

The `len` builtin now returns a value of type `Int`.

```ab
// Before
len(text) // Returns `Num` value

// After
len(text) // Returns `Int` value
```

# Text to Bool Casting Warning 

Casting `Text` to any values including `Bool` and `Int`, now issues an "absurd cast" warning. While not an error, it indicates a potential logical issue and encourages explicit conversion for clarity.

```ab
// Before
echo "true" as Bool then 1 else 0 // OK

// After
echo("true" as Bool then 1 else 0) // Warning: Absurd cast
```

# Escaping Changes

## String Literal Escaping Changes 

A bug related to the escaping of `$` sequences within string literals has been fixed. Previously, `"\$variable"` would incorrectly interpolate the value of `variable` instead of treating `$` as a literal character. If your code inadvertently relied on the previous buggy behavior where `\$` within a string literal was interpolated, you will now observe the correct behavior where `\$` is treated as a literal dollar sign. You may need to adjust your string literals if you intended interpolation in such cases.

```ab
// Before
let var = 45
echo "\$var" // Output: 45

// After
let var = 45
echo("\$var") // Output: \$var
```

## Command String Escaping Changes 

The internal handling of text within commands has been refactored, leading to a breaking change in how double quotes (`"`) should be escaped within command strings. Previously, `"` might have been escaped with `\"` in some contexts, but this is no longer the correct behavior.

Double quotes (`"`) should *not* be escaped with a backslash (`\`) when used within command strings. The parser now handles this automatically. If your code contains command strings where double quotes are escaped (e.g., `$ echo \"hello\" $`), you must remove the backslash.

```ab
// Before (will now cause an error or incorrect behavior)
trust $ printf \"Amber\" $ // Incorrect: will now be interpreted as a literal backslash followed by a double quote

// After (correct behavior)
trust $ printf "Amber" $ // Correct: the double quote is handled by the parser
```

# Standard Library Updates

## Redesigned `std/date`

The standard library’s Date module has been completely overhauled. We improved how its functions compose, removed obsolete ones, and repurposed others. The complete list of changes is below.

| Old Name | New Name | Description |
|:--|:--|:--|
| `date_posix` | `date_from_posix` | Converts textual representation in a default `YYYY-MM-DD HH:MM:SS` format to [unix epoch time](https://en.wikipedia.org/wiki/Unix_time) |
| *new* | `date_format_posix` | Converts [unix epoch time](https://en.wikipedia.org/wiki/Unix_time) to a textual representation. |
| `date_add` | `date_add` | Adds time to passed date. |
| *new* | `date_sub` | Subtracts time to passed date. |
| *removed* | `date_compare` | Compares two dates and returns value of a sign function. |

## Regex Functions Compatibility Changes 

To improve cross-platform compatibility, especially with macOS and BusyBox environments, the standard library functions `match_regex()` and `replace_regex()` no longer support certain GNU Sed-specific regular expression features. If your existing code relies on these GNU Sed-specific features within `match_regex()` or `replace_regex()`, you will need to update your regular expressions to use POSIX-compliant alternatives. For example, instead of `\b`, you might use `[[:<:]]` and `[[:>:]]` for word boundaries, or ensure you are using ERE for alternation (`|`).

The following regular expression features are no longer supported within `match_regex()` and `replace_regex()`:
*   `\b` (word boundary) in both Extended Regular Expressions (ERE) and Basic Regular Expressions (BRE).
*   `|` (alternation) in Basic Regular Expressions (BRE).

## Function Renaming 

The standard library function `parse_number` has been renamed to `parse_num` to align with the new `Int` data type and improve clarity. If your code directly calls `parse_number`, you will need to update these calls to `parse_num`.

```ab
// Before
const num_val = trust parse_number("123.45")

// After
const num_val = trust parse_num("123.45")
```

## Functions Now Failable 

Several standard library functions that previously returned a `Bool` to indicate success or failure have been updated to be failable functions. This change aligns with Amber's failable paradigm, providing a more consistent and robust error handling mechanism. These functions no longer return a `Bool`. Instead, they will either succeed or fail, triggering the failable mechanism (e.g., propagating failure with `?` or being caught by a `failed` block).

**Affected Functions:**
- `std/fs::symlink_create`
- `std/fs::dir_create`
- `std/fs::file_chmod`
- `std/fs::file_chown`
- `std/net::file_download`

```ab
// Before
if dir_create("my_directory") {
    echo "Directory created successfully."
} else {
    echo "Failed to create directory."
}

// After
dir_create("my_directory") exited(code) {
    if code == 0:
        echo("Directory created successfully.")
    else:
        echo("Failed to create directory.")
}
```

## Removed `env_const_get` Function

The `env_const_get` function has been removed from `std/env`. Use `env_var_get` instead, which provides the same functionality.

```ab
// Before
env_const_get("VAR")

// After
env_var_get("VAR")
```

---

## File: docs/nightly-alpha/getting_started/testing.md

Test blocks are dedicated scopes for writing tests. They are executed only when running the `amber test` command and are ignored during normal compilation. Test blocks can be optionally named using a string literal. This improves readability and allows for targetted execution.

## Syntax
```ab
import { assert } from "std/test"

// Unique named test block
test "can multiply numbers" {
    let result = 10 * 2
    assert(result == 20)
}

// Unnamed test block (only one allowed per file)
test {
    let name = "Amber"
    assert(name + " Lang" == "Amber Lang")
}
```

# CLI Test Filtering

The `amber test` command is designed to verify the correctness of your code by executing test blocks. By default, it recursively finds and runs all tests in the current directory. You can narrow down which tests to run by providing filter arguments.

## Filtering Tests

You can run a specific subset of tests by providing a filter argument. This argument performs a substring match against both the **filename** and the **test name**.

```bash
# Run all tests located in the current directory containing "variable" in their name or filename
amber test . "variable"
```

## Targeting Specific Files

Instead of running tests from the current directory, you can specify a particular file or directory to scan.

```bash
# Run all tests inside main.ab
amber test main.ab

# Run all tests in main.ab that contain "zip" in their name
amber test main.ab "zip"
```

---

## File: docs/nightly-alpha/getting_started/usage.md

The Amber CLI can be used as a runtime or as a compiler.

## Command Line Interface

The Amber CLI syntax uses subcommands, like the Git CLI:

*This output is generated from the 0.5.2-alpha version.*
```
Usage: amber [OPTIONS] [INPUT] [ARGS]... [COMMAND]

Commands:
  eval        Execute Amber code fragment
  run         Execute Amber script
  check       Check Amber script for errors
  build       Compile Amber script to Bash
  docs        Generate Amber script documentation
  completion  Generate Bash completion script
  test        Run Amber tests
  help        Print this message or the help of the given subcommand(s)

Arguments:
  [INPUT]    Input filename ('-' to read from stdin)
  [ARGS]...  Arguments passed to Amber script

Options:
      --no-proc <NO_PROC>  Disable a postprocessor
                           Available postprocessors: 'bshchk'
                           To select multiple, pass multiple times with different values
                           Argument also supports a wildcard match, like "*" or "b*chk"
  -h, --help               Print help
  -V, --version            Print version
```

For detailed usage instructions, refer to the [Amber usage guide](https://docs.amber-lang.com/getting_started/usage).

### Running Amber Code

The following command will simply execute `hello.ab` as a script file. Amber code will be compiled to Bash and then executed all in one go:

```sh
$ amber run hello.ab
Hello world!
```

Alternatively, if the file contains a _shebang_ line and has the executable bit set, it can be run like this:

```ab
#!/usr/bin/env amber
echo("Hello world")
```

```sh
$ ./hello.ab
Hello world
```

Additionally, command line arguments can be passed to the script:

```ab
#!/usr/bin/env amber
main(args) {
    for arg in args {
        echo(arg)
    }
}
```

```sh
$ ./args.ab 1 2 3
1
2
3
```

### Preventing Execution with Bash

If you write an Amber script with a shebang pointing to `amber`, there is a risk that someone might accidentally execute it with `bash` instead. To prevent this, you can add a check at the top of your script using the following technique:

```ab
// 2> /dev/null; exit 1

// Your Amber code here
echo("Hello world")
```

This line is valid in both Amber and Bash:
- In **Amber**, `//` starts a comment, so the line is ignored
- In **Bash**, `//` is treated as a comment (ignored), `2> /dev/null` suppresses errors, and `exit 1` terminates the script with an error code

For more information about running Amber scripts, see [Running Amber Code](#running-amber-code).

If you want to run just a small code snippet, you can do that as well:

```sh
$ amber eval '
import * from "std/text"
echo(uppercase("Hello world!"))
'
HELLO WORLD!
```

### Compiling Amber Scripts

There are times when you prefer to just compile Amber code to a script, for example when dealing with _cron jobs_:

```sh
$ amber build input.ab output.sh
```

You’ll notice that the compiled script is immediately callable; hence, there’s no need to add executable permissions using `chmod`, for instance. Amber grants the permission automatically.

Furthermore, Amber adds a _shebang_ at the top of the compiled script. This enables you to run the code simply, without any additional commands:

```sh
$ ./output.sh
```

## Testing

Amber comes with a built-in test runner. You can define named test blocks in your code and execute them using the `amber test` command.

```sh
$ amber test
```

For more details on writing and filtering tests, please refer to the [Testing guide](https://docs.amber-lang.com/getting_started/testing).

## Syntax Highlighting

[VS Code](https://code.visualstudio.com) as well as [Zed](https://zed.dev) now have built-in LSP integration.

![Amber LSP Feature]{"width": "100%"}(/images/lsp-example-light.webp)(/images/lsp-example-dark.webp)

Here is a list of plugins that support syntax highlighting for Amber language.

| Icon | Name | Location |
|---|:----:|:-----:|
| LOGO:hx | **Helix Editor** | [Native Support](https://docs.helix-editor.com/lang-support.html) |
| LOGO:kate | **Kate/KWrite** | [GitHub](https://github.com/amber-lang/amber-kate) |
| LOGO:nova | **Nova** | [Nova extensions](https://extensions.panic.com/extensions/besya/besya.amber/) |
| LOGO:vim | **Vim** | [Our extension repository](https://github.com/amber-lang/amber-vim) |
| LOGO:vsc | **VS Code** | [VSC Marketplace](https://marketplace.visualstudio.com/items?itemName=Ph0enixKM.amber-language) or [Our extension repository](https://github.com/amber-lang/amber-vsc) |
| LOGO:zed | **Zed** | Zed extensions or [Our extension repository](https://github.com/amber-lang/zed-amber-extension) |
|| **JetBrains** | [JetBrains extension](https://plugins.jetbrains.com/plugin/32151-amber-language) | 


## Other interesting commands

### Postprocessors

Amber supports postprocessors that can optionally run after compilation to enhance your scripts. These tools are not included with Amber but will be executed automatically if they are installed on your system.

#### bshchk

[bshchk](https://github.com/b1ek/bshchk) is a runtime Bash dependency checker. It analyzes your compiled Bash script to ensure all external commands used are available at runtime, preventing runtime failures due to unavailable dependencies.

**Features:**
- Detects missing external commands before script execution
- Prevents runtime failures due to unavailable dependencies
- Supports inline directives for fine-grained control

For installation instructions and usage details, please refer to the [bshchk README](https://github.com/b1ek/bshchk#readme).

### Minification

Additionally, the `--minify` option compresses the generated Bash code to reduce its size:

```sh
$ amber build --minify input.ab output.sh
```

### Generating Amber Documentation

The following command extracts comments prefixed with `///` (triple slashes) from a single Amber file, and generates a Markdown file for documentation, by default in the `docs` subdirectory:

```sh
$ amber docs stdlib.ab
```

### Generating Bash Completion Scripts

The following command generates a [Bash completion](https://en.wikipedia.org/wiki/Command-line_completion) script:

```sh
$ amber completion
_amber() {
    local i cur prev opts cmd
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
...
```

This can be sourced in the `.bashrc` file via command redirection, so that command completion works in all subsequently opened Bash shells.  Assuming the `amber` binary is on the system path:

```sh
$ cat ~/.bashrc
...
source <(amber completion)
...
```

### Disabling the Optimizer

The optimizer is still being improved. If you encounter any issues with optimization, you can disable it using an environment variable:

```sh
AMBER_NO_OPTIMIZE=1 amber ...
```

### Custom Header and Footer

Amber allows you to customize the header and footer of compiled scripts using environment variables:

**AMBER_HEADER**: Path to a custom header file that replaces the default header. The header can use template variables:
- `{{ version }}` - Amber compiler version

**AMBER_FOOTER**: Path to a custom footer file that appends to the end of the script. The footer can use:
- `{{ version }}` - Amber compiler version

**Example custom header (`custom_header.sh`):**
```bash
#!/usr/bin/env bash
# Custom header for production scripts
# Project: {{ version }}
# Generated on: $(date)
```

**Example custom footer (`custom_footer.sh`):**
```bash
# Custom footer
# End of generated script
```

**Usage:**
```sh
# Using custom header
AMBER_HEADER=./custom_header.sh amber build input.ab output.sh

# Using both header and footer
AMBER_HEADER=./custom_header.sh AMBER_FOOTER=./custom_footer.sh amber build input.ab output.sh
```

**Default header:**
```bash
#!/usr/bin/env bash
# Written in [Amber](https://amber-lang.com/)
# version: {{ version }}
```

Note: Custom headers and footers are useful for adding project-specific metadata, license information, or runtime checks to your compiled scripts.

---

## File: docs/nightly-alpha/getting_started/whats_new.md

> WARNING: Brief description of new changes TBD when releasing

# Union Types
Union types provide a flexible way to define function parameters that can accept values of multiple distinct types.

```ab
fun print_value(val: Int | Text | Bool) {
    echo(val)
}

print_value(42)       // Valid
print_value("Amber")  // Valid
print_value(true)     // Valid
```

# Testing suite
Amber now features a built-in testing suite. It allows you to write dedicated `test` blocks that are only executed when running the `amber test` command.

We also introduced a new `std/test` library. More on that in the [Standard library improvements](#standard-library-improvements) section.

```ab
test "can multiply numbers" {
    let result = 10 * 2
    // assertions ...
}
```

You can also name your tests for better readability and filter them by name or filename using CLI arguments. Read more in the [Testing Guide](testing).

# Improved variable diagnostics

The compiler now surfaces clearer warnings when variables are not used, helping you catch mistakes earlier. It also warns when a variable declared with `let` is never modified, encouraging the use of `const` for bindings that never need reassignment.

```ab
let unused = 1 // Warning: variable 'unused' is not used
let count = 3  // Warning: variable 'count' is never modified - consider using 'const'
echo(count)

```

# New builtins syntax

All builtins like `echo` now have new syntax similar to functions:

```ab
echo("Hello world")
cd("newdir")
mv("file.ab", "newdir")
exit(1)
```

# Array Type Resolution

Amber now supports type inference for empty arrays `[]`. You can initialize an empty array without specifying its type immediately. The type will be resolved later based on how the array is used, such as in assignments, binary operations, or function calls.

```ab
let arr = [] // Type is generic
arr += [1]   // Resolved to [Int]
```

# Array destructing

You can now destruct arrays into separate variables:

```ab
let arr = [1,2,3]
let [key1, key2, key3] = arr

echo("{key1} {key2} {key3}") // 1 2 3
```

# Standard library improvements

> WARNING: Brief description of new changes TBD when releasing

## New `std/test` module

We introduced a new [`std/test`](stdlib/doc/test) library that provides `assert` and `assert_eq` functions to help you write tests.

```ab
import { assert, assert_eq } from "std/test"

test "can multiply numbers" {
    let result = 10 * 2
    assert(result == 20)
    assert_eq(result, 20)
}
```

## New `fetch` function for HTTP requests

The `fetch` function provides a functionality for making HTTP requests. It intelligently utilizes available command-line tools for network operations, with a failover to bash's network sockets. This function supports a comprehensive set of HTTP methods, including `GET`, `POST`, `PUT`, and `DELETE`.

```ab
import { fetch } from "std/http"

let response = trust fetch("https://example.com")
let post_request = trust fetch("https://example.com", "POST", "hello world!", [ "content-type: text/plain" ]) // POST request
```

---

## File: docs/nightly-alpha/contribute/compiler.md

The Amber compiler follows a standard compilation pipeline to transform Amber source code into Bash scripts.

```mermaid
flowchart LR
    Lexer --> Parser
    Parser --> TypeCheck[Type Checker]
    TypeCheck --> Translator
    Translator --> Optimizer
    Optimizer --> Renderer
```

1.  **Lexer**: Transforms source code text into a stream of tokens (Keywords, Operators, Identifiers, etc.).
2.  **Parser**: Consumes tokens to build an Abstract Syntax Tree (AST), representing the code structure.
3.  **Type Checker**: Traverses the AST to validate types, ensure safety, and infer missing type information.
4.  **Translator**: Converts the typed AST into an intermediate representation called `FragmentKind` (Lower IR).
5.  **Optimizer**: Performs optimizations on the intermediate representation.
6.  **Renderer**: Converts the final IR into the target Bash string.

Here you will find out how the compiler is structured, how the parser works and how to write new syntax modules. Let's begin!

## Lexer

Beforehand the code is transformed into an array of tokens that contain information about:
- `word` - the token content
- `pos` - the token location in the document (row, column)
- `start` - the index in the code string where the token starts

```rs
struct Token {
    word: String,
    pos: (usize, usize),
    start: usize
}
```

Tokens are created with lexical rules that are contained in the [src/rules.rs](https://github.com/amber-lang/amber/blob/master/src/rules.rs) file.

Here is the example of how an array of Amber tokens can look like, where strings represent instances of `Token`:
```js
[Token<"let">, Token<"is_alive">, Token<"=">, Token<"true">, ...]
```

## Parser

Parser takes in Tokens and forms an Abstract Syntax Tree that represents the code written in Amber.

### Syntax Module

What transforms tokens into the AST (Abstract Syntax Tree) is a `SyntaxModule`. It can be a `Text` literal, `echo` builtin or `Add` operator. The `SyntaxModule` is a trait that implements:
- `parse` method that parses the module and determines whether or not the corresponding token string represents this sytax module. If otherwise, then a `Failure::Quiet` is returned that means that this is not the correct module to parse the tokens. However if this is the correct module but an error is encountered, then `Failure::Loud` is returned with an error (or warning / info) is returned.
- `new` method that instantiates a new SyntaxModule.
- `syntax_name!("<name of this module>")` that identifies this syntax module with its name.

The most important method here is `parse` that is defined with the following signature:

```rs
fn parse(&mut self, meta: &mut M) where M: Metadata -> SyntaxResult;
```

Parsing returns a `SyntaxResult` that under the hood is represented as `Result<(), Failure>`. It means that parsing can be finished successfully or it can fail returning a `Failure` object.

Here is an example `SyntaxModule` that parses `Bool` literal:
```rs
impl SyntaxModule for Bool {
    syntax_name!("Bool");

    fn new() -> Self {
        Bool {
            value: false
        }
    }

    fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
        let value = token_by(meta, |value| ["true", "false"].contains(&value.as_str()))?;
        self.value = value == "true";
        Ok(())
    }
}
```

### Metadata

You can see that in the `parse` method mentioned above we pass some object called `meta`. This is a metadata parameter of type `ParserMetadata` that inherits from `Metadata` provided by Heraclitus. The structure instance is carried through the parsing process to keep a track of current state. It holds information such as declared variables, functions, boolean parameters telling if current context is within a loop or a function etc. `ParserMetadata` is represented as:

```rs
struct ParserMetadata {
    // Parsing contenxt
    pub context: Context
    // Error / Warning messages
    pub messages: Vec<Message>
    // ...
}
```

You can find out more about this structure in [src/utils/metadata/parser.rs](https://github.com/amber-lang/amber/blob/master/src/utils/metadata/parser.rs) file.

### Parsing Flow

The journey starts with parsing the global `Block` that can be located in [src/modules/block.rs](https://github.com/amber-lang/amber/blob/master/src/modules/block.rs) file. The `Block` parses a sequence of statements (`Statement` located in [src/modules/statement/stmt.rs](https://github.com/amber-lang/amber/blob/master/src/modules/statement/stmt.rs)).

#### Statement

Statement (`Statement`) is a structure that can represent any `SyntaxModule` that is of statement type. In other words Statement is a wrapper for syntax modules that represents a statement type such as loop, if condition, variable declaration etc.

```rs
struct Statement {
    value: Option<StmtType>
}
```

Here we can see that the `value` field accepts `StmtType` enum that is declared above and represents a syntax module.

```rs
enum StmtType {
    Expr(Expr),
    VariableInit(VariableInit),
    VariableSet(VariableSet),
    IfCondition(IfCondition),
    // ...
}
```

Statement is built of a macro `parse_statement!` that can be located in [src/modules/statement/stmt.rs](https://github.com/amber-lang/amber/blob/master/src/modules/statement/stmt.rs). The syntax modules provided to the macro are parsed sequentially in the order from top to bottom. This means that the parser will first try to match `Import` and then `FunctionDeclaration`. The expression  (`Expr` located in [src/modules/expression/expr.rs](https://github.com/amber-lang/amber/blob/master/src/modules/expression/expr.rs)) is passed as the final parameter to the `parse_statement!` macro so that it's parsed at the very end.

```rs
parse_statement!([
    Import,
    FunctionDeclaration,
    // ...
    Expr
], ...);
```

This macro iterates through the provided syntax modules and attempts to parse them one by one. If a module successfully parses the code, the loop breaks and the result is returned.

The `StatementDispatch` derive macro is used on the `StmtType` enum to automatically generate dispatch methods for traits like `TranslateModule`, `TypeCheckModule`, etc. preventing the need to verify matches manually.

#### Expr

Expression (`Expr` located in [src/modules/expression/expr.rs](https://github.com/amber-lang/amber/blob/master/src/modules/expression/expr.rs)) represents a syntax that is a value of certain type (also referred to as _kind_ because of the Rust's type keyword). For example `1 + 1` is an addition of type `Num`.

```rs
struct Expr {
    // The value of the expression
    value: Option<ExprType>,
    // The type of the expression
    kind: Type,
    // The position of the expression
    position: Option
}
```

Analogically to `Statement`, expression also is a wrapper for syntax modules that are of expression type. Instead of `StmtType` enum `ExprType` is declared.

```rs
enum ExprType {
    Bool(Bool),
    Number(Number),
    Text(Text),
    Add(Add),
    Sub(Sub),
    // ...
}
```

Since certain expressions require different approaches to parsing, there is a different macro used here to automate the process. There are a couple of different types of expressions:
- `TernOp` - a ternary operator that is parsed from right to left. It's used for conditional ternary operator.
- `BinOp` - a binary operator that is parsed from left to right.
- `UnOp` - a unary operator that is parsed from left to right, where the symbol expression is on the left side.
- `TypeOp` - a binary expression that is represented as expression followed by operator and then a type. Example of such operator is a cast operator: `12 as Bool`.
- `Literal` - a Literal that doesn't have any directional precedence. Literal is the final group of expression precedence.

The hierarchy of the groups is represented within the `parse_expression!` macro (defined in [src/modules/expression/macros.rs](https://github.com/amber-lang/amber/blob/master/src/modules/expression/macros.rs)). It returns an Expr` that has been parsed.

begin[details] How exactly does parsing expressions work?

```rs
let result = parse_expression!(meta, [
    ternary @ TernOp => [ Ternary ],
    range @ BinOp => [ Range ],
    addition @ BinOp => [ Add, Sub ],
    multiplication @ BinOp => [ Mul, Div, Modulo ],
    types @ TypeOp => [ Is, Cast ],
    unops @ UnOp => [ Neg, Not ],
    literals @ Literal => [ Bool, Number, Text ]
]);
```

The pattern that the macro follows can be represented as `<function_group_name> @ <group_type> => [<syntax_modules>]`. The macro is declared as a recurrent relation of functions (groups) that are calling each other (inside of an internal macro `parse_expr_group!`).

```rs
let result = {
    fn _terminal(...) {
        panic!("Please end the recurrence in the group before");
    }

    fn literal(...) {
        parse_expr_group!(... {literal, _terminal} ...);
    }

    // ...

    fn range(...) {
        parse_expr_group!(... {range, addition} ...);
    }

    fn ternary(...) {
        parse_expr_group!(... {ternary, range} ...);
    }

    return ternary(...);
};
```

The main objective of `parse_expr_group!` is to implement given function's body with appropriate parsing mechanism. If it's a `BinOp` that parses from left to right, then first we parse left expression by calling the lower order group, then we parse the operator, and then the right expression. You can read more on how parsing groups works in the macros file.

end[details]

### Type Checking

After the parsing phase is completed, the Compiler performs a Type Check that validates types of variables and expressions. This logic is contained within the `TypeCheckModule` trait located in [src/modules/typecheck.rs](https://github.com/amber-lang/amber/blob/master/src/modules/typecheck.rs).

```rs
pub trait TypeCheckModule {
    fn typecheck(&mut self, meta: &mut ParserMetadata) -> SyntaxResult;
}
```

This method is called after parsing but before translation. It allows the module to infer types, check for type mismatches, and mutate the module state (e.g. storing the inferred type) using the `ParserMetadata`.

### Translation

The next step is translating the AST into an Intermediate Representation (Fragments) which is structurally closer to the target language (Bash). This is handled by the `TranslateModule` trait located in [src/translate/module.rs](https://github.com/amber-lang/amber/blob/main/src/translate/module.rs).

```rs
pub trait TranslateModule {
    fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind;
}
```

This method takes `TranslateMetadata` and transforms the module into a `FragmentKind`.

### FragmentKind

`FragmentKind` is a crucial enum that represents a piece of generated code. It serves as an intermediate representation that abstracts over different types of Bash constructs before they are rendered into the final string. It is defined in [src/translate/fragments/fragment.rs](https://github.com/amber-lang/amber/blob/main/src/translate/fragments/fragment.rs).

```rs
pub enum FragmentKind {
    Raw(RawFragment),
    VarExpr(VarExprFragment),
    VarStmt(VarStmtFragment),
    Block(BlockFragment),
    Interpolable(InterpolableFragment),
    List(ListFragment),
    Subprocess(SubprocessFragment),
    Arithmetic(ArithmeticFragment),
    Comment(CommentFragment),
    Log(LogFragment),
    #[default] Empty
}
```

Its purpose is to provide structured generation of Bash code. For example:
- `VarExpr` handles variable access (like `$VAR`).
- `Subprocess` handles `$(...)` command substitutions.
- `Block` handles sequences of statements (like `{ ... }`).
- `Arithmetic` handles `(( ... ))` arithmetic contexts.

`FragmentKind` implements `FragmentRenderable` trait which allows it to be converted to a string. This is the final stage of compilation where Lower IR is rendered into actual Bash code:

```rs
fn to_string(self, meta: &mut TranslateMetadata) -> String;
```

---

## File: docs/nightly-alpha/contribute/contribute.md

Welcome to the Amber Contributing Guidebook! 👋

This guide offers a clear and comprehensive introduction to getting started with contributing to Amber. If you haven’t already, consider joining our [Discord](https://discord.com/invite/cjHjxbsDvZ) community, where you can ask any questions and connect with other contributors.

## Contributing Guidelines

Before you dig into Amber, you should know a few things before you contribute.

Any code change is submitted [through a PR](https://github.com/amber-lang/Amber/pulls), which is then approved by at least 2 maintainers. Each pull request should be directed to the `staging` branch unless there is a specific justification for targeting the `master` branch.

The way we talk on GitHub is not the same as we would talk in person. When on GitHub, always get straight to the point and be critical.

Personal grudges are forbidden around here, as well as anything offtopic or offensive.

### Opening a PR

Before a PR is opened, it usually has an issue about it first, where we discuss how exactly a feature must be implemented, to avoid making a mistake.

It is recommended that you see how features were already implemented. A good example is [#130](https://github.com/amber-lang/Amber/issues/130)

To create a PR, you should fork the repo, create a branch, do your work in there, and open a PR. It will then be reviewed and pushed into master.

The maintainers will check who it is the best reviewer, we suggest to open a ticket reporting the issue before starting to do the PR so we can discuss the implementation.

### Getting Help

Along the way, you may need help with your code. The best way to ask is in [our Discord server](https://discord.com/invite/cjHjxbsDvZ), but you may also ask other contributors personally or post in [Discussions](https://github.com/amber-lang/Amber/discussions).

### Development

Compile Amber with the following instructions:

```
git clone https://github.com/amber-lang/amber
cd amber
cargo build
```

In order to execute amber code, use the following command:

```bash
# `cargo run` - cargo command
# `run <file.ab>` - amber command
cargo run run <file.ab>
```

To compile amber code into a bash code, use the following command:

```bash
# `cargo run` - cargo command
# `build  <output.sh>` - amber command
cargo run build  <output.sh>
```

Debugging Amber:
```bash
# Displays Amber's AST trace of trying to parse code
AMBER_DEBUG_PARSER=true cargo run -- run <file.ab>
# Shows the time it took to compile each phase
AMBER_DEBUG_TIME=true cargo run -- run <file.ab>
# Flamegraph is a profiling tool that is used to visualize the time each function took to execute
sudo cargo flamegraph -- <file.ab> <file.sh>
```

#### Running Tests

Tests modules can be found in [`src/tests`](https://github.com/amber-lang/amber/tree/main/src/tests). Modules like [`erroring.rs`](https://github.com/amber-lang/amber/blob/main/src/tests/erroring.rs), [`stdlib.rs`](https://github.com/amber-lang/amber/blob/main/src/tests/stdlib.rs) and [`validity.rs`](https://github.com/amber-lang/amber/blob/main/src/tests/validity.rs) load test scenarios from directories `src/tests/erroring/`, `src/tests/stdlib/` and `src/tests/validity/` respectively.

To run ALL tests, run `cargo test`.

If you want to run only tests from a specific module, let's say from [`stdlib.rs`](https://github.com/amber-lang/amber/blob/main/src/tests/stdlib.rs), you can do that by adding the module name to the command: `cargo test stdlib`.

To run a single test case, for example `function_with_wrong_typed_return.ab` in `erroring`, you can filter by the test name:
`cargo test function_with_wrong_typed_return`

#### Github Actions

We use GitHub Actions to run tests and build binaries. When a new release tag is created, artifacts are built for Linux, macOS, and Windows (x86_64 and aarch64) and uploaded to the release page. We also generate installers and Debian packages.