starlark-rust: a Rust implementation of the Starlark configuration language
A Rust implementation of the Starlark language
At a glance
- What is it?
- starlark-rust is Meta's Rust implementation of Starlark, the deterministic Python-inspired language used for configuration in Bazel, Buck and Buck2. It ships six crates, a linter and an LSP, and it deliberately does not promise API stability between releases.
- Who is it for?
- starlark-rust fits a Rust codebase that wants to embed a deterministic, sandboxable configuration language, and that can live with a semver-guaranteed but API-unstable library. It does not fit a team that needs to run arbitrary Python or needs a stable API across major versions, and the stack overflow behaviour on circular data structures is a real constraint for untrusted scripts.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A configuration language, not a scripting language
Starlark is a deterministic language inspired by Python 3, used for configuration in the build systems Bazel, Buck and Buck2, and this project is Meta's Rust implementation of it. Buck2 depends on this library.
Determinism is the defining constraint. A build system configuration language has to produce the same result on every machine and every run, which rules out the reflection, mutable global state and nondeterministic iteration that make general scripting languages convenient and make them unsuitable for reproducible builds. The upstream specification lives with the Bazel project.
The lineage is worth noting because it explains the API shape. The project was originally developed in the google/starlark-rust repository, which contains a more extensive history, and version 0.4.0 of the library changed ownership from Google to Meta. The canonical repository is facebook/starlark-rust, and the README notes there are several copies of it on GitHub.
The stated audience is people embedding a configuration language into their own tool. Starlark is not trying to replace Python for scripting, and the README says as much when it suggests considering Python3 instead of the bundled binary if you only want vanilla Starlark.
Six crates and which one you actually need
The workspace is split into six components, and picking the right one is the first practical decision.
`starlark` is the main library, with the evaluator, the standard library, debugger support and other pieces. Projects embedding Starlark into their own environment, with extra types and library functions, use this one. It reexports the relevant pieces of `starlark_derive`, `starlark_map` and most of `starlark_syntax`.
`starlark_derive` is a proc-macro crate defining the necessary macros. It is a dependency of `starlark` and should not be used directly. `starlark_map` holds memory-efficient ordered and unordered maps and sets, plus other data structures useful in Starlark. `starlark_syntax` holds the AST and the parsing functions, and the README says to use it only if you want to manipulate the AST directly.
Then there are `starlark_lsp`, which provides a Language Server Protocol implementation, and `starlark_bin`, the binary exposing interactive evaluation, IDE features and the linter through a command line.
The README's warning about `starlark_bin` is the most useful advice in the whole document. The binary can be used effectively as a linter, but its REPL, evaluator and IDE features only know standard Starlark. Since most embeddings supply extra functions and data types for domain-specific work, using the bundled binary will make the REPL and evaluator fail on those and will give a subpar IDE experience. The recommendation is to write your own binary on top of the `starlark` and `starlark_lsp` libraries.
Trying it: the REPL in three commands
The README gives a quick way to see the language in action, and it is worth doing before deciding anything.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo runThe first command installs the Rust toolchain, the second starts the project, and the REPL then evaluates what you type. The README shows a one-line session:
$> 1+2
3That is a complete first use, from a fresh clone to evaluating an expression, in two commands. The Rust toolchain is the only prerequisite, since the project is a Cargo workspace.
For a real integration, the dependency is the `starlark` crate from crates.io, and the API documentation is published on docs.rs under the `starlark` name, with the README carrying a crates.io version badge for it. The workspace itself also contains a `starlark_js_example` directory and a `benchmark/` directory, and the `vscode/` directory holds an extension that the README says you can still use if you build your own binary on top of the LSP functions.
Garbage collection, frozen values and Send/Sync
The feature list is short and the interesting items are the Rust-specific ones.
Interoperability between Rust types and Starlark is the headline: you can expose your own native types to scripts. The types are Rust-friendly in a specific way, where frozen values are `Send` and `Sync` while non-frozen values are not. That distinction matters for anyone running Starlark evaluation across threads, since it tells you exactly which values can be shared without locking.
Values are garbage collected and allocated on a heap, with the collector documented separately in `docs/gc.md`. Types are optionally runtime-checked, documented in `docs/types.md`, which is the difference between a dynamic script that fails at the point of misuse and one that fails earlier at a defined boundary.
Around the language there is tooling: a linter to detect code issues in Starlark, LSP support for IDE integration, DAP support for the Debug Adapter Protocol, and extensive testing including fuzz testing through the oss-fuzz project.
The `starlark_map` crate is where the memory-efficiency work lives, with ordered and unordered maps and sets built for the allocation patterns of script workloads, and the workspace pulls in `blake3` for hashing and `indexmap` for insertion-ordered maps.
Where it diverges from the Starlark spec
The README has a compatibility section, and it is short enough that you should read it before assuming parity.
There are plenty of extensions to the standard, such as type annotations, recursion and top-level `for`. The implementation does not yet support later additions to Starlark, with `bytes` named as an open issue tracked in the repository. And in some cases creating circular data structures may lead to stack overflows.
That last point deserves attention for anyone evaluating untrusted input. A language embedded in a build system or a linter often runs scripts the author did not write, and a stack overflow on a circular structure is a crash rather than a clean error. It is a documented limit, not a hidden one, but it is the kind of thing you want to know before you wire a script runner to a service.
The other comparison point is the other implementations. There are at least three, one in Java at bazelbuild/starlark, one in Go at google/starlark-go, and this one in Rust. The project mostly follows the Starlark standard, so if you are porting behaviour between the Java and Rust implementations, the compatibility list above is where the differences live.
No API stability, but SemVer rules
The project states two non-goals that shape every upgrade you will do.
The first is that it does not aim for API stability between releases, preferring to iterate quickly and refine the API as much as possible. The second is that it does not aim for minimal dependencies, preferring to keep one package with lots of power, though feature flags may be added if some dependencies prove tricky. Despite that, the project says it does follow SemVer.
Those two statements together are the upgrade story. SemVer means a breaking change shows up in the version number, so your Cargo.toml gives you a signal. No API stability means you should expect to rework your integration code when you take a major bump, and that the 0.x line before 1.0 carries no such promise at all.
The release history shows the pace. Tags include v0.12.0 on 2024-02-09, v0.13.0 on 2024-12-13, and v0.14.0 on 2026-06-01. The repository is not archived and the last push was on 2026-10-15, so work continues between releases.
The publishing procedure is spelled out too, and it explains a detail that surprises people. The `starlark` and `starlark_derive` versions have to be bumped and published in a defined order, with the `starlark` dependency pointing at the latest `starlark_derive` version, and the release procedure is to run `cargo publish --allow-dirty --dry-run` first and then without the dry run, in each component directory in order. That is why a Cargo.toml can end up pointing at a `starlark_derive` version that is newer than the `starlark` version you see.
Editorial conclusion
starlark-rust fits a Rust codebase that wants to embed a deterministic, sandboxable configuration language, and that can live with a semver-guaranteed but API-unstable library. It does not fit a team that needs to run arbitrary Python or needs a stable API across major versions, and the stack overflow behaviour on circular data structures is a real constraint for untrusted scripts. Before adopting it, run `cargo run` to try the REPL, read the compatibility notes on where it diverges from the Starlark spec, and check the `starlark` and `starlark_derive` version numbers you pin, since those two are published separately and must be bumped together.
Frequently asked questions
What is starlark-rust?
It is Meta's Rust implementation of the Starlark language, a deterministic language inspired by Python 3 used for configuration in Bazel, Buck and Buck2. Buck2 depends on this library, and it is licensed under Apache License 2.0.
How do I try Starlark in Rust quickly?
Install the Rust toolchain with the rustup script, then run `cargo run` in a clone of the repository to start the REPL, where expressions such as `1+2` are evaluated immediately. The crate is also published on crates.io as `starlark` with docs on docs.rs.
Which crate should I depend on to embed Starlark?
The `starlark` crate, which has the evaluator, standard library and debugger support and reexports the relevant pieces of the other crates. `starlark_derive` should not be used directly, and `starlark_syntax` is only for direct AST manipulation.
Does starlark-rust fully match the Starlark specification?
Not exactly. It has plenty of extensions such as type annotations, recursion and top-level for, it does not yet support later additions such as bytes, and in some cases creating circular data structures may lead to stack overflows.
Is the starlark-rust API stable between releases?
No. The project states it does not aim for API stability between releases and prefers to iterate quickly, though it does follow SemVer. The latest tag is v0.14.0 from 2026-06-01 and the last push was on 2026-10-15.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/facebook-starlark-rust)Was this useful?