Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Salam Programming Language

The Salam Programming Language - زبان برنامه نویسی سلام

Salam Programming Language

Salam is a general-purpose and systems programming language designed for efficient software development, featuring a built-in domain-specific language (DSL)

Discord GitHub Release GitHub repository size

Salam Programming Language Playground

Compiler - Build & Test Compiler - Clone & Build Compiler - Build & Release Editor - Playground (WebAssembly) Books - Build & Validate PDFs Lint - Super-Linter Lint - Prek Standard Hooks Lint - Prek Manual Hooks Lint - Prek Audit Hooks PR - Pull Request Labeler Dependabot Updates GitHub Pages Build Deployment VS Code Marketplace Version VS Code Marketplace Installs


✨ Introducing Salam

Salam Language, inspired by the word salam (سلام), meaning peace, is engineered for exceptional efficiency, reliability, and modern software development. Designed from the ground up to balance low-level control with developer productivity, Salam eliminates the unnecessary syntactic friction often found in systems engineering. By prioritizing a clean, scannable, and intuitive architecture, it lowers the cognitive barrier to entry, fostering an accessible and inclusive environment for building high-performance software.

Supported Languages

Why Choose Salam?

Key Features

🧩 Editor Support

Visual Studio Code

Install the official Salam Language extension from the Visual Studio Code Marketplace for syntax highlighting and language support.

Install on VS Code

🛠️ The Compiler (salam)

Salam is statically typed and compiled. The general language transpiles to C and is built to a native executable; embedded layout: blocks compile to HTML/CSS/JS.

Build

Requires a C compiler. tcc is the default backend (bundled math, fast); gcc/clang also work.

The compiler lives in compiler/ (a self-contained subproject: src/, std/, tests/, tools/, Makefile, CMakeLists.txt). Build it from there:

cd compiler
sh tools/bash/build-compiler.sh   # quick build with tcc  ->  ./salam
# or, with CMake (out-of-tree build, then run the test suite via ctest):
cmake -B build && cmake --build build && ctest --test-dir build
# or just: make            # (release build via the Makefile -> ../salam at the repo root)

There is no separate runtime library: salam build emits the small C runtime (print/strcat/pow/alloc and optional bounds checks) inline into the generated C, so compiled programs are self-contained and link only -lm (-lmsvcrt with tcc).

Usage

# general language -> native executable
salam build app.salam --output=app.exe         # then ./app.exe
salam cli build app.salam --keep-c             # optional 'cli' prefix; keep generated C
salam obj app.salam                            # compile to .o only

# layout DSL -> website
salam layout build page.salam                  # page.html + page.css + page.js
salam layout build page.salam --inline         # one self-contained page.html
salam layout build a.salam b.salam             # per-page html + merged style.css/script.js

# inspect any stage (general or layout)
salam app.salam --emit-tokens-xml | --emit-ast-xml | --emit-symbol-xml
salam app.salam --log-level=trace
salam build app.salam -DDEBUG                  # preprocessor define

# format source in place (auto-detects nothing - pass --lang=fa for Persian files)
salam fmt app.salam                            # reformat one file
salam fmt                                      # reformat every .salam under the cwd, recursively
salam fmt compiler/src/ examples/              # reformat given files and/or directories
salam fmt --check                              # report files that need formatting (exit 1 if any)
salam fmt app.salam --tabs                     # indent with tabs (convert spaces to tabs)
salam fmt compiler/src/ --indent=2             # indent with 2 spaces per level
salam fmt page.salam --lang=fa                 # Persian source

# REPLs
salam cli       # general
salam layout    # layout

Hello, World:

func main {
    println("Hello, World!")
}

Cross-compilation

Salam can produce executables and object files for other operating systems and architectures using the LLVM backend. Pass a full LLVM target triple with --target=<triple> to build or obj; when it is present the compiler routes through LLVM (clang/llc) instead of the default C backend, so --cc and --keep-c no longer apply. The output name follows the target’s conventions (.exe for Windows, .obj for MSVC objects, none for ELF), and --output overrides it as usual.

# Windows executable from Linux (MinGW target)
salam build main.salam --target=x86_64-w64-windows-gnu --output=app.exe

# WebAssembly (WASI)
salam build main.salam --target=wasm32-wasi --output=app.wasm

# a target-specific object file
salam obj main.salam --target=x86_64-pc-windows-msvc      # -> main.obj

The target is fully wired through the pipeline: the OS/arch predefined macros (SALAM_OS_WINDOWS, SALAM_ARCH_X64, …) describe the target, so @if SALAM_OS_WINDOWS selects the right branch, and link "..." directives are passed to the cross-linker (e.g. link "user32"-luser32).

Prerequisites. Cross-compilation drives the LLVM toolchain, so you need a recent clang/llc (v22 is what the toolchain invokes) plus, for Windows targets, the LLVM linker lld and a sysroot (the target’s CRT, system import libraries, and headers):

sudo apt install clang lld llvm        # toolchain (or an official LLVM release)

Bundled sysroot (zero-setup for your users). Build the compiler with -DSALAM_BUNDLE_MINGW=ON and a MinGW-w64 sysroot is staged into <prefix>/share/salam/sysroots/<arch>-w64-mingw32/; salam build --target=…-windows-gnu then discovers and passes it automatically, so end users need nothing extra:

# copy an existing sysroot (e.g. from the mingw-w64 package)
cmake -B build -DSALAM_BUNDLE_MINGW=ON \
      -DSALAM_MINGW_SYSROOT=/usr/x86_64-w64-mingw32
# or download one (pin the hash for reproducibility)
cmake -B build -DSALAM_BUNDLE_MINGW=ON \
      -DSALAM_MINGW_URL=<llvm-mingw archive> -DSALAM_MINGW_SHA256=<hash>
cmake --build build && cmake --install build

Point $SALAM_SYSROOTS at a directory holding per-target sysroot subdirectories to override or add targets without rebuilding. Automatic discovery names them by toolchain, not by the raw triple: <arch>-w64-mingw32/ for *-windows-gnu (e.g. x86_64-w64-mingw32/) and <arch>-linux-musl/ for *-linux-musl (e.g. x86_64-linux-musl/).

MSVC / macOS targets. Automatic sysroot discovery currently handles only MinGW (*-windows-gnu) and musl (*-linux-musl). Microsoft’s and Apple’s SDKs are not redistributable and aren’t auto-discovered, so for *-windows-msvc and *-apple-darwin you must supply a toolchain/sysroot yourself (e.g. xwin for MSVC) and drive clang manually via salam llvm until first-class selection for those targets lands. On Linux, prefer the -windows-gnu (MinGW) triple.

The LLVM backend supports a growing subset of the language; cross-compilation works for self-contained programs and their imports within that subset. Host-native builds without --target continue to use the fast C backend (tcc/gcc/clang) and the full standard library.

🐳 Docker & Docker Compose

The compiler ships a multi-stage Dockerfile and a docker-compose.yml built on Alpine Linux (musl, the lightest practical base). The build context is the compiler root (compiler/). The image includes everything the compiler needs: a C compiler (gcc + tcc), the LLVM 22 backend (clang-22, llc-22, opt-22, lli-22), and make, no CMake required.

The compose file lives in compiler/docker/; pass it with -f so you can run from the repository root. There are two modes:

Development (live reload)

The compiler tree is bind-mounted and ./salam is recompiled automatically on every change to src/ (powered by entr, see tools/bash/docker-dev.sh):

docker compose -f compiler/docker/docker-compose.yml up dev   # build, then watch & rebuild

Edit any file under compiler/src/ on your host and the container rebuilds ./salam incrementally. To get a shell inside the same environment:

docker compose -f compiler/docker/docker-compose.yml run --rm dev sh

Production (copy & build)

The production stage runs COPY . then make && make install, baking a fully built, self-contained compiler into the image. salam is the entrypoint, and the repository root is mounted at /work so shared examples/ are reachable:

docker compose -f compiler/docker/docker-compose.yml build prod
docker compose -f compiler/docker/docker-compose.yml run --rm prod build examples/en/basics/hello.salam --output=hello
docker compose -f compiler/docker/docker-compose.yml run --rm prod layout build page.salam --inline
docker compose -f compiler/docker/docker-compose.yml run --rm prod --help

Plain Docker (without Compose)

Build with compiler/ as the context (so the Dockerfile’s COPY . picks up the compiler tree):

docker build --target prod -f compiler/docker/Dockerfile -t salam:prod compiler   # production image
docker run --rm -v "$PWD":/work salam:prod build app.salam --output=app

docker build --target dev  -f compiler/docker/Dockerfile -t salam:dev  compiler   # dev image
docker run --rm -it -v "$PWD/compiler":/app salam:dev                             # live-rebuild loop

The LLVM and Alpine versions are configurable build args (--build-arg LLVM_VERSION=22, --build-arg ALPINE_VERSION=edge). LLVM 22 currently lives in Alpine’s edge repositories, which is why edge is the default base.

Books (XeLaTeX)

The tutorial books have their own image under books/docker/ so you can typeset them without installing a local TeX distribution. One common XeLaTeX image builds both languages: it is based on the full TeX Live scheme, which already bundles xepersian (for the heavier right-to-left Persian book), polyglossia + tcolorbox (for the lighter English book) and Latin Modern. The books/ tree is bind-mounted, so the generated PDFs are written back to the host at books/<lang>/intro-programming/book.pdf:

docker compose -f books/docker/docker-compose.yml run --rm books        # both
docker compose -f books/docker/docker-compose.yml run --rm books en     # English only
docker compose -f books/docker/docker-compose.yml run --rm books fa     # Persian only

Or with plain Docker (build once, then run against the mounted books/ tree):

docker build -t salam-books books/docker
docker run --rm -v "$PWD/books":/books salam-books all

🚀 Bun Workspaces: Multi-App Development & Static Site Guide

🚀 1. Quickstart Execution Guide

To kick off your entire localized monorepo environment simultaneously, run the following steps from your root directory.

bun install
bun run dev:all

Your terminal window will display interleaved logs, cleanly prefixed by their respective package origins:

Salam % bun run dev:all
$ bun run --filter='*' --parallel dev
@workspace/pages:dev         |
@workspace/pages:dev         |   VITE v8.1.3  ready in 61 ms
@workspace/pages:dev         |
@workspace/pages:dev         |   ➜  Local:   http://127.0.0.1:55002/
@workspace/editor:dev        |
@workspace/editor:dev        |   VITE v8.1.3  ready in 65 ms
@workspace/editor:dev        |
@workspace/editor:dev        |   ➜  Local:   http://127.0.0.1:55001/
@workspace/vercel-editor:dev |
@workspace/vercel-editor:dev |   VITE v8.1.3  ready in 91 ms
@workspace/vercel-editor:dev |
@workspace/vercel-editor:dev |   ➜  Local:   http://localhost:5173/
@workspace/vercel-editor:dev |   ➜  Network: use --host to expose
@workspace/runner:dev        |
@workspace/runner:dev        |  ⛅️ wrangler 4.107.0
@workspace/runner:dev        | ────────────────────
@workspace/runner:dev        | ⎔ Starting local server...
@workspace/runner:dev        | [wrangler:info] Ready on http://localhost:8787
@workspace/runner:dev        | [wrangler:info] GET / 200 OK (7ms)

📁 2. Monorepo Architecture & Core Setup

To configure the workspace, structure your repository directory tree alphabetically as follows:

salam-monorepo/
├── bunfig.toml
├── package.json
├── editor/
├── extensions/
│   └── vscode/
├── pages/
├── runner/
└── vercel-editor/

Root Configuration Files

package.json (Workspace Root)

This file defines the workspaces in strict alphabetical order and leverages Bun’s parallel filtering mechanics. It also centralizes shared dependency versions via Bun’s workspace catalog and exposes root scripts for local development, builds, Wrangler type generation, and dependency updates.

{
  "name": "salam-monorepo",
  "private": true,
  "workspaces": {
    "packages": [
      "editor",
      "extensions/vscode",
      "pages",
      "runner",
      "vercel-editor"
    ],
    "catalog": {
      "react": "^19.2.7",
      "react-dom": "^19.2.7",
      "tailwindcss": "^4.3.2",
      "@tailwindcss/vite": "^4.3.2",
      "@vitejs/plugin-react": "^6.0.3",
      "vite": "^8.1.3",
      "typescript": "^6.0.3",
      "wrangler": "^4.107.0",
      "@types/bun": "latest",
      "@types/node": "^26.1.0",
      "@types/react": "^19.2.17",
      "@types/react-dom": "^19.2.3"
    }
  },
  "scripts": {
    "dev:all": "bun run --filter='*' --parallel --if-present dev",
    "dev:editor": "bun run --filter='@workspace/editor' dev",
    "docs:myst": "bun run myst start",
    "dev:pages": "bun run --filter='@workspace/pages' dev",
    "dev:runner": "bun run --filter='@workspace/runner' dev",
    "dev:vercel": "bun run --filter='@workspace/vercel-editor' dev",
    "build:all": "bun run --filter='*' --if-present build",
    "build:myst": "bun run myst build --html",
    "build:vercel": "bun run --filter='@workspace/vercel-editor' build",
    "update:deps": "bun update -i -r",
    "clean": "rm -rf node_modules **/node_modules .bun-cache",
    "generate": "bun run --filter='@workspace/runner' generate",
    "typecheck": "bun run --filter='@workspace/runner' typecheck"
  },
  "devDependencies": {
    "@tailwindcss/vite": "catalog:",
    "@vitejs/plugin-react": "catalog:",
    "mystmd": "^1.10.1",
    "vite": "catalog:"
  }
}

Useful root commands:

bunfig.toml (Workspace Root)

Forces Bun to persistently treat execution environments with development-first behaviors.

[development]
development = true

🛠️ 3. Static Site Package Implementation

The independent workspace utilizes your specific package scope (@workspace/pages). It is set to "private": true to protect against accidental package publishing to the public npm registry.

Static Site Configuration

pages/package.json

{
  "name": "@workspace/pages",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "bunx vite --port 55002 --host 127.0.0.1"
  }
}

⚡ 4. The Serve Methods Evaluated

Depending on your asset compilation pipelines, you can run and serve your static file assets via two distinct command-line approaches.

Method A: Bun Native Dev Engine (bun run --watch index.html)

Bun acts as a full-stack compiler. It looks for runtime entry points, hooks a watcher loop, and injects code straight into the runtime.

PORT=55002 bun run --watch index.html

Method B: The Local Isolation Method (bunx vite)

Bypasses complex multi-environment integrations entirely by mounting a dedicated Vite development context over the directory.

bunx vite --port 55002 --host 127.0.0.1

🔄 5. Global Monorepo Package Updates

To manage and upgrade your external dependencies across all application subdirectories together without navigating into individual package folders, trigger your custom root shortcut:

bun run update:deps

Explaining the Flags Behind the Script (bun update -i -r)

When initialized, Bun appends a Workspace column to your terminal output grid so you can verify exactly where every target module upgrade is bound before writing the changes to disk.


🔒 6. Security Breakdown & Best Practices

When operating servers on your host machine, observe these boundaries:

The Port Selection Architecture

Network ports scale from 1 to 65535.

Network Address Binding (0.0.0.0 vs 127.0.0.1)

Safe Command Formula

To enforce instant browser updates, skip disk caches, isolate network eavesdroppers, and bypass compiler engine crashes, use this script formula:

bunx vite --port 55002 --host 127.0.0.1

📚 7. MyST Documentation

The repository ships a MyST (Markedly Structured Text) docs site powered by mystmd. Source content comes from books/ (TeX book files) and .md files across the repository.

Configuration Files

Running the Documentation Locally

# Install workspace dependencies (includes mystmd)
bun install

# Start the live-reload docs server
bun run docs:myst

# Build the static HTML output to _build/html/
bun run build:myst

The dev server (myst start) watches books/ and .md files across the repository and rebuilds on changes. Read the Docs uses .readthedocs.yaml to autobuild and deploy the site.

🤝 Contributing

We welcome contributions from the community!

Together, let’s make coding accessible to all.


🔍 Joining Code Reviews

Everyone is welcome, and encouraged, to participate in code reviews. You do not need to be a core maintainer to review a pull request. In fact, reviewing PRs is one of the most impactful ways to contribute to Salam, and we want to make it as approachable as possible.

💡 Code review is harder than writing code. Reading someone else’s work, understanding their intent, spotting edge cases, and communicating feedback kindly and clearly takes real skill. If you are doing it, thank you; it matters enormously.

How a GitHub PR Review Works

Open any pull request, then click the Files changed tab to see a diff of every file that was modified.

Leaving an inline comment

  1. Hover over any line number in the diff; a blue + button appears.

  2. Click it to open a comment box for that specific line or block.

  3. Write your thought, then click Start a review (not “Add single comment”) so all your notes are batched together.

Suggesting a code change

Inside an inline comment you can propose an exact replacement using a fenced suggestion block:

```suggestion
your replacement code here
```

The author can accept your suggestion with a single click, no manual editing required.

Submitting the review

When you have finished reading all the files:

  1. Click the green Review changes button (top right of the diff).

  2. Write an overall summary comment.

  3. Choose one of three outcomes:

    • 💬 Comment - share thoughts without formally approving or blocking. Great for questions, first-timer feedback, or discussion starters.

    • Approve - you are satisfied with the changes. This is the green tick that moves a PR toward merging. Only approve if you have read the changes carefully.

    • 🚫 Request changes - something needs to be fixed before the PR can merge. Be specific and constructive.

  4. Click Submit review.

Tips for great reviews

Growing with the Community

Consistent reviewers and contributors are noticed. Active participation in reviews, issues, and discussions is how community members become trusted collaborators. Over time, standout contributors may be invited to join the Salam core team and take on additional responsibilities:

💬 Real-Time Community

The Salam core team lives in our real-time channels. Join us to ask questions, share ideas, discuss reviews in progress, or just say hello:

These spaces are open to everyone, from curious newcomers to experienced systems programmers. The more voices the better.


📖 Glossary

Terms used across this readme, the Contributing Guide, and the editor readme.

TermDefinition
Alpine LinuxLightweight Linux distribution built on musl libc. Used as the base image for Salam’s Docker containers.
AST (Abstract Syntax Tree)Tree representation of parsed source code. Each node represents a construct (expression, statement, declaration). The Salam compiler builds an AST before semantic analysis and code generation.
BiomeFast JavaScript/TypeScript linter and formatter. Run as a prek hook (biome-check).
BunJavaScript runtime, package manager, and bundler. Used in the Salam monorepo to manage workspaces and run dev servers.
C ABIC Application Binary Interface, the low-level contract for how functions are called and data is laid out in memory. Salam’s FFI and extern "C" declarations rely on the C ABI.
CI (Continuous Integration)Automated pipeline that builds, tests, and lints every pull request. Salam uses GitHub Actions for CI.
ClangLLVM-based C compiler. One of the supported backends for building the Salam compiler.
Cloudflare WorkersServerless compute platform that runs JavaScript/TypeScript at the edge. The runner/ workspace deploys to Cloudflare Workers via Wrangler.
CMakeCross-platform build tool generator. The Salam compiler can be built with cmake -B build && cmake --build build.
CodegenCode-generation backend. Transforms the compiler’s AST and type information into target output (C source, LLVM IR, or a WebAssembly module).
CodespellSpell checker for source code and documentation. Run as a prek hook to catch typos.
CTestCMake’s built-in test runner. Invoked with ctest --test-dir build after a CMake build of the compiler.
deferSalam keyword that schedules a statement or block to run at the end of the enclosing scope, regardless of how the scope is exited.
DockerContainer platform used to build and run the Salam compiler in an isolated, reproducible environment.
Docker ComposeTool for defining and running multi-container Docker applications. Salam provides a docker-compose.yml in compiler/docker/ with dev and prod service targets.
doctocTool that auto-generates a Table of Contents inside Markdown files. The TOC blocks in this readme and the Contributing Guide are maintained by doctoc.
DSL (Domain-Specific Language)A language tailored to a specific problem domain. Salam includes a built-in layout DSL that compiles .salam files to HTML, CSS, and JavaScript.
EmscriptenLLVM-based toolchain that compiles C/C++ to WebAssembly. Used to build salam-wa.wasm and salam-wa.js for the web playground.
entrUtility that re-runs a command whenever watched files change. Used in Salam’s Docker dev mode to rebuild the compiler on source edits.
FFI (Foreign Function Interface)Mechanism for calling functions written in another language (typically C). Salam supports FFI via extern "C" declarations.
ForkA personal copy of a repository on GitHub. Contributors fork SalamLang/Salam, work in their fork, then open a pull request back to the original.
GCCGNU Compiler Collection. A C compiler supported by the Salam build tool.
GitleaksSecret-detection tool run as a prek audit hook to prevent accidental commits of API keys or credentials.
GitHub ActionsSalam’s CI/CD platform. Workflows are defined in .github/workflows/.
Layout DSLSalam’s built-in sublanguage for describing UIs. layout: blocks, or .salam files processed with salam layout build, compile to HTML, CSS, and JavaScript.
LexerFirst stage of the compiler pipeline: reads source text and produces a stream of tokens.
LLVMLow Level Virtual Machine, a compiler infrastructure project. Used as an optional backend (clang-22, llc-22, opt-22, lli-22 are included in the Docker image).
MakefileGNU Make build script (compiler/Makefile). Running make from compiler/ produces a release build of the salam binary at the repository root.
MarkdownlintLinter for Markdown files. Enforces consistent style in README.md, CONTRIBUTING.md, and other docs.
muslA C standard library used by Alpine Linux. Salam’s Docker images are based on Alpine + musl for a minimal footprint.
MyST (Markedly Structured Text)Documentation toolchain that extends Markdown with roles, directives, and cross-references for technical writing. Configured via myst.yml; driven by the mystmd package (scripts docs:myst and build:myst).
npmNode Package Manager. Used alongside Bun for package management in the Salam monorepo.
ParserSecond stage of the compiler pipeline: consumes the token stream from the lexer and builds an AST.
PR (Pull Request)A GitHub mechanism for proposing changes: a contributor opens a PR from a feature branch, reviewers comment, and a maintainer merges it.
prekGit hook manager used by Salam. Hooks are defined in prek.toml (standard and manual stages) and prek-audit.toml (security-focused audit checks).
prek-audit.tomlprek configuration file for security-focused audit hooks. Run separately with prek run --all-files --config prek-audit.toml.
PrettierOpinionated code formatter for JavaScript, TypeScript, CSS, and JSON. Run as a prek hook.
ReactJavaScript library for building user interfaces with a component model. Used in the vercel-editor/ workspace.
Read the DocsFree documentation hosting platform. Salam’s MyST docs are automatically built and published there via .readthedocs.yaml.
REPLRead-Eval-Print Loop, an interactive session where you type expressions and see results immediately. salam cli starts a general REPL; salam layout starts a layout REPL.
RTL (Right-to-Left)Text direction used by Arabic and Persian scripts. The Salam web playground supports RTL and switches direction when the Persian language is selected.
Semantic AnalyzerThird stage of the compiler pipeline: resolves names, checks types, and validates the AST before code generation.
SemVer (Semantic Versioning)Version numbering scheme (MAJOR.MINOR.PATCH). Used by Bun’s interactive update tooling and GitHub releases.
shfmtShell script formatter. Run as a prek manual-stage hook to normalise indentation and style in .sh files.
Super-LinterGitHub Actions workflow that runs a broad set of language-specific linters across the repository in CI.
Tailwind CSSUtility-first CSS framework. Used in the Salam monorepo workspaces; integrated via the @tailwindcss/vite plugin.
TCC (Tiny C Compiler)Lightweight, fast C compiler. The default backend used by Salam’s quick-build script.
Tree-walking interpreterAn interpreter that evaluates the AST directly without first compiling to native code. Used by the web playground and via salam exec / salam run --interp for pure-compute programs.
TUI (Terminal User Interface)Interactive, keyboard-driven interface rendered in the terminal. Bun’s bun update -i flag opens a TUI for selecting which packages to upgrade.
TypeScriptTyped superset of JavaScript that compiles to plain JavaScript. Used in the runner/ and vercel-editor/ workspaces.
UpstreamThe original SalamLang/Salam repository. Contributors add it as a Git remote (git remote add upstream …) to keep their fork in sync.
Virtual filesystemEmscripten’s in-browser filesystem layer. build-wasm.sh preloads the std/ directory into it so import resolution and the layout schema work when running Salam in the browser.
ViteFrontend build tool and dev server. Used in the Salam monorepo to serve the editor and pages workspaces.
WebAssembly (Wasm)Portable binary instruction format that runs at near-native speed in modern browsers. Salam’s web playground is powered by a Wasm build of the compiler produced by Emscripten.
WranglerCloudflare’s CLI for building and deploying Workers. The runner/ workspace uses Wrangler for local development (wrangler dev) and CI type generation.
yamllintYAML linter. Run as a prek hook to validate .yml workflow and configuration files.

© 2024-2026 Salam Language Team