# ArkScript: a Lisp-shaped scripting language for embedding in C++

> ArkScript is a small, Lisp-inspired scripting language whose core fits under 8000 lines of C++ and compiles to bytecode for a portable virtual machine. It suits teams that want a scripting layer inside a host application, and it comes with hard edges: eight types, nine keywords, and an upstream that refuses LLM-written patches.

**ArkScript-lang/Ark** — ArkScript is a small, fast, functional and scripting language for C++ projects

- Repository: https://github.com/ArkScript-lang/Ark
- Website: https://arkscript-lang.dev/
- Stars: 736 · Forks: 54
- Language: C++
- License: MPL-2.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/arkscript-lang-ark

## ArkScript is a Lisp-shaped scripting language built to be embedded in C++

ArkScript is a small, Lisp-inspired scripting language written in C++ for embedding into C++ applications. The README puts the size first: the core fits under 8000 lines of code, the language has only 9 keywords, and 8 types are enough to represent any data you might need. It is not offered as a general purpose system language. The case it serves is a host application that wants a configuration and scripting layer its end users can extend without recompiling the host. Two properties shape everything else: every parameter is passed by value, and everything is immutable unless a script explicitly says otherwise. The upside is that a script cannot quietly mutate a value the host also holds. The cost is that anything needing mutation has to be written that way from the start. C++ authors get in by registering their own functions in the language, which the README describes as easy.

## Macros and C++ modules are two different ways to extend the language

Because the language is Lisp inspired, code is data and can be manipulated through macros, and the README lists that as a headline feature with an example file for it in the examples directory. ArkScript offers two routes to new behaviour, and they suit different needs. The macro route stays inside the language. A macro is limited to what the language evaluation model can express, and it is the right tool when you want new shorthand that expands into calls that already exist. The C++ module route goes the other way. It lets host code add functionality that scripts call into, with the C++ side of the standard library living in lib/modules/ next to the ArkScript parts in lib/std/. A module is the right tool when you need access to the host process, a native library or operating system facilities that the language has no syntax for. For a team that already owns a C++ codebase, the module route is where the real integration work happens, and it is also where the language stops being portable.

## One bytecode format and one virtual machine make the same file run anywhere

The compiler emits a bytecode format that a virtual machine executes, and that is the mechanism behind the portability claim: the same bytecode runs on any machine where the VM is built. The README mentions an optimising compiler and links to a benchmarks page, while being upfront that performance is a secondary concern and that expressiveness is the priority. For a scripting layer that runs at startup or in response to a user action, the more useful property is predictable behaviour across platforms rather than raw speed. Packaging follows the same split, with two Docker Hub images. The stable image is built after each release, and the nightly image is built after each commit, so a pipeline can pin to a release and still follow the tip when it wants to. The repository also ships a CHANGELOG.md at the top level, which is where the differences between consecutive versions are written down.

## Pulling an image, then running the Fibonacci example as a smoke test

The README gives two installation routes. The fastest is to pull one of the published images and run the language inside it:
```bash
docker pull arkscript/stable:latest
```
If you want the newest commits rather than the last release, the nightly image is built after every commit:
```bash
docker pull arkscript/nightly:latest
```
The other route is to build the project with CMake and install the result with CMake:
```bash
cmake --install build
```
A first program is one expression, and the Fibonacci example in the README is short enough to serve as a smoke test:
```clojure
(let fibo (fun (n)
  (if (< n 2)
    n
    (+ (fibo (- n 1)) (fibo (- n 2))))))

(print (fibo 28))  # display 317811
```
Running that file should print 317811. The shape of the code is worth reading before anything else: parentheses everywhere, a let binding a lambda, recursion calling that binding by name, and a trailing comment that states the expected output. The same style shows up across the examples directory, where factorial.ark, collatz.ark, fizz_buzz.ark and closures.ark sit next to a games folder and a calendar example.

## A REPL, a formatter you cannot configure, and a standard library in two languages

Three conveniences are built into the project. There is a REPL with autocompletion and colouration, and an online playground where a snippet can be tried before any local build. There is a code formatter that the README calls opinionated and non-configurable, which is a deliberate constraint: every user gets the same output, but there is no setting to change it, and a team with an existing house style has no hook for that. The standard library is split by language, with ArkScript code under lib/std/ and C++ under lib/modules/, and the related repositories separate the standard library, the standard library modules and a documentation generator. ArkScript also supports C++ modules generally, described in the README as a way to add functionality to the language from the host side.

## Upstream refuses LLM-written issues and patches, and asks agents to prove it

One contribution rule is unusual enough that a team should read it before planning an upstream patch. The README states a strict no LLM and no AI policy: no LLMs for issues, no LLMs for patches and pull requests, and no LLM-generated comments on the bug tracker, translation included. There is a second mechanism behind that policy. The README asks that an agent appending a marker to an issue or pull request also compute a number such that the last commit hash on the dev branch, written on seven characters and prefixed by that number, produces a SHA256 starting with nine leading zeros. The stated purpose is to filter out careless bots. In practice this means a human submitting on behalf of an assistant has to satisfy a rule that is easy to get subtly wrong, and that a project comfortable with assistants in its private code still has to write its upstream work by hand.

## Eight types, nine keywords and value semantics are the ceiling on what you can model

The smallness that makes embedding pleasant also sets limits, and the README is upfront about them. Everything is passed by value and everything is immutable unless specified, so host data structures that scripts must modify need an explicit convention, and the shown documentation does not spell out a full mapping between script values and C++ types. The feature list has no object system, and the library surface is a set of functions rather than a type hierarchy. The formatter adds a smaller but real constraint: an opinionated formatter with no configuration means a project that formats its own C++ and shell scripts differently has to accept ArkScript's own layout, or fork the formatter. None of this makes the language unusable, but it does mean the eight types have to fit the problem domain before you start, rather than being extended later if they do not.

## MPL-2.0, three releases in four months, and a dev default branch

ArkScript is licensed under MPL-2.0, a file level copyleft licence, so modified MPL-covered files have to be published when you distribute them, while your own files stay under your own terms. Whether that fits your distribution model is a question for your own counsel, not for the README. On the release side, v4.7.1 was published on 2026-06-21, v4.7.2 on 2026-08-14 and v4.8.0 on 2026-10-11, so minor versions arrive within weeks of each other rather than on a long schedule. The default branch is dev rather than a release branch, and the last push was on 2026-10-19, eight days after the v4.8.0 tag, which means the tip of the default branch is post release work. The practical upgrade cost is a changelog read each time you bump the pinned version, plus the review of any behaviour change in the C++ module interface.

## Conclusion

Adopt ArkScript if you are shipping a C++ application and want end users to extend it with a small scripting layer written in Lisp style code, and if you can live with eight types, nine keywords and value semantics. Do not adopt it if your users need object oriented scripting, mutable shared state, or a standard library you do not want to write yourself, since the standard library lives in separate repositories and the formatter cannot be configured. Before committing, run the Fibonacci example from the README through the stable Docker image, read CHANGELOG.md for the changes between v4.7.2 and v4.8.0, and confirm that the C++ modules under lib/modules/ can reach the host functions you actually need. The last push was on 2026-10-19 and v4.8.0 shipped on 2026-10-11, so pin the tag rather than tracking the dev branch.

## FAQ

### What is ArkScript?

ArkScript is a small, Lisp-inspired scripting language written in C++ for embedding into C++ projects. Its core fits under 8000 lines of code, it has 9 keywords and 8 types, and the compiler produces bytecode that the virtual machine runs.

### How do I install ArkScript?

The README gives two options: pull the stable or the nightly Docker image, or build the project with CMake and install it with cmake --install build. The stable image is rebuilt after each release and the nightly image after each commit.

### Does ArkScript support macros and C++ modules?

Yes to both. It is a Lisp inspired language where code is data and can be manipulated through macros, and it supports C++ modules that add functionality callable from the language, with the C++ side of the standard library living under lib/modules/.

### Can I contribute to ArkScript using an LLM?

No. The README states a strict no LLM and no AI policy covering issues, pull requests and bug tracker comments. The repository also asks agents to append a marker and a computed number that makes the dev branch commit hash produce a SHA256 starting with nine leading zeros.

## Sources

- [ArkScript-lang/Ark on GitHub](https://github.com/ArkScript-lang/Ark)
- [License: MPL-2.0](https://github.com/ArkScript-lang/Ark/blob/dev/LICENSE)
- [Project website](https://arkscript-lang.dev/)
- [README](https://github.com/ArkScript-lang/Ark/blob/dev/README.md)
- [Releases](https://github.com/ArkScript-lang/Ark/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/arkscript-lang-ark
