Scryer Prolog: an ISO Prolog implementation in Rust, from source to first query
A modern Prolog implementation written mostly in Rust.
At a glance
- What is it?
- Scryer Prolog is an ISO-oriented Prolog system written mostly in Rust, with clp(B), clp(ℤ), DCGs, attributed variables and tabling. Here is how it installs, what its architecture commits to, and where it still falls short.
- Who is it for?
- Adopt Scryer Prolog if you want an ISO-conformant Prolog with clp(B), clp(ℤ), DCGs, attributed variables and tabling in one binary, and you are willing to build it with Rust 1.93.1 or newer. Do not adopt it if you depend on a large third-party pack ecosystem or on the WAM JIT and precise compacting GC that the README still lists as unfinished.
- Can I use it commercially?
- Yes. BSD-3-Clause 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 last received commits 11 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Scryer Prolog is trying to be, and who that serves
The README states the goal directly: Scryer Prolog "aims to become to ISO Prolog what GHC is to Haskell: an open source industrial strength production environment that is also a testbed for bleeding edge research in logic and constraint programming, which is itself written in a high-level language." That sentence sets the audience. This is not a teaching toy and not a scripting convenience. It is aimed at people who write Prolog as the primary language of a program and who care whether the standard is followed.
The evidence for that positioning is conformance, not feature count. The README says Scryer passes all tests of syntactic conformity, of variable_names/1, and of dif/2, with links to Ulrich Neumerkel's test pages. Those three suites probe different things: whether terms read and write in standard syntax, whether the system can report the names of variables in a query, and whether dif/2 behaves as a sound disequality constraint rather than as negation. A system that passes all three is making a claim about correctness that most small Prolog implementations do not attempt.
The secondary audience is people who want a Prolog they can embed or extend. The Cargo.toml declares crate-type = ["cdylib", "rlib"], so the same code that produces the command line binary can be linked as a Rust library or loaded as a C dynamic library. The feature flags in Cargo.toml split the build into all-pure, all-simple-cross, ffi, tls, http and crypto-full, which tells you the maintainers think about cross-compilation and about which dependencies are pure Rust versus which pull in OpenSSL or ring. That is the shape of a project meant to be built into other things.
The WAM first, the standard second: how the implementation is layered
The README describes the work in three phases, and the layering matters more than the checklist. Phase 1 was to "produce an implementation of the Warren Abstract Machine in Rust, done according to the progression of languages in Warren's Abstract Machine: A Tutorial Reconstruction." That book is checked into the repository as wambook/wambook.pdf, so the implementation follows a published derivation rather than an ad hoc interpreter loop. Phase 1 is described as complete in some form, covering lists, cuts, Debray allocation, first argument indexing, last call optimization and conjunctive queries.
Phase 2 is where the language becomes usable: call/N as a meta-predicate, ISO throw/catch, user-defined operators with custom fixity and precedence, bignum, rational and floating point arithmetic, a module system, term_expansion/2 and goal_expansion/2, DCGs, attributed variables using the SICStus interface, if_/3, all-solutions predicates, assert and retract with logical update semantics, backtrackable and non-backtrackable globals, delimited continuations via reset/3 and shift/1, a tabling library built on those continuations, clp(B), clp(ℤ), streams with a sockets library, and an incremental compilation and loading process written primarily in Prolog.
Phase 3 is the part that has not happened. The README says the intent is to use the WAM code produced by the code generator to get JIT-compiled and executed Prolog programs, and that "the question of how to get assembly from WAM code is something I'm still considering." Two items in the Phase 2 list are also explicitly unfinished: replacing choice points that pivot on inlined semi-deterministic predicates with if/else ladders, and inlining all built-ins and system call instructions. Demand-driven indexing over all arguments is marked in progress with a link to a pull request, and the precise compacting garbage collector is marked in progress. Read the checklist as a roadmap with live edges, not as a finished product page.
Installing Scryer Prolog from binaries, cargo, or a git checkout
The README gives three routes. The fastest is a precompiled binary: the download page is https://github.com/mthom/scryer-prolog/releases/latest, and the most recent release listed is v0.10.0 from 2025-09-27. If your platform is covered, this avoids the toolchain question entirely.
The second route is cargo install from the repository, which is what the README shows for people who already have Rust:
cargo install --locked --git https://github.com/mthom/scryer-prolog.gitAfter that command the README says the scryer-prolog binary will be in $HOME/.cargo/bin, a directory usually added to PATH during Rust installation. The --locked flag makes cargo respect Cargo.lock, so you get the dependency versions the maintainers tested rather than the newest compatible ones.
The third route is a local checkout, which is what you want if you intend to read the source or run the test suites:
$> git clone https://github.com/mthom/scryer-prolog
$> cd scryer-prolog
$> cargo build --releaseThe README notes that --release performs optimizations and produces a faster executable, and that the resulting binary appears in target/release. It also warns that Scryer tends to use features from newer Rust releases, that distribution packages and Macports lag behind, and that rustup is the recommended way to stay current. The exact minimum is not in the README prose: it says to read the package.rust-version key in Cargo.toml, where the value is 1.93.1, and that CI validates the accuracy of that number. The crate uses edition 2024, which is consistent with a recent toolchain requirement.
Once the binary is on your PATH, the README's own example of invoking the system is the binary name itself, and the dif/2 test suite it cites is the behaviour worth checking first: dif/2 should delay rather than fail, and a later binding should be reported with the constraint discharged. If you plan to embed the system instead of running it interactively, build with the default feature set, which Cargo.toml defines as all-simple-cross, tls and http.
What the feature flags and the Dockerfile tell you about deployment
Cargo.toml is unusually explicit about why features are grouped the way they are, and that grouping is the deployment story. The default feature set is all-simple-cross, tls and http. The all-pure feature, defined as repl plus hostname, is described as activating "all features that depend on no non pure-rust dependencies," and the comment notes it currently excludes ffi because of libffi, tls and http because of openssl, and crypto-full because of ring. The all-simple-cross feature adds ffi and crypto-full to all-pure, and the comment says it covers everything except tls and http, again because those depend on openssl.
That means a static or musl-style build with no OpenSSL is reachable by turning off tls and http, at the cost of the networking predicates those flags gate. If you are shipping Scryer into a container, the repository's Dockerfile shows the maintainers' own approach: a three-stage cargo-chef build. The planner stage runs cargo chef prepare to produce recipe.json, the cacher stage runs cargo chef cook --release against that recipe, and the builder stage copies the cached target directory and runs cargo build --release --bin scryer-prolog. The final image is debian:bookworm-slim with openssl installed, the binary copied to /usr/local/bin, RUST_BACKTRACE=1 set in the environment, and an entrypoint of /usr/local/bin/scryer-prolog.
One detail in that Dockerfile is worth copying into your own pipeline even if you do not use Docker: the build runs scryer-prolog --version as a sanity check, and the comment says the build should fail if the binary cannot be executed because of missing libraries. A version check that fails the build catches missing shared objects at image build time rather than at first query.
Where Scryer Prolog is the wrong tool
The clearest limitation is stated by the project itself, in the Phase 3 section: the JIT-compiled execution of WAM code does not exist yet, and the author is still considering how to get assembly from WAM code. If your workload depends on compilation to native code for throughput, Scryer is not that system today, and the README does not promise a date.
The second gap is memory management. The precise compacting garbage collector satisfying the five properties of the cited paper is marked in progress. Until that lands, long-running processes with heavy term churn carry a risk the README does not quantify. That is not a reason to avoid the system for short-lived queries, but it is a reason to measure before you put it behind a long-lived service.
The third gap is the one the README is quietest about: there is no mention of a package manager, a pack registry, or a third-party library ecosystem. Phase 2 lists built-in libraries such as clp(B) and clp(ℤ), and the repository has a learn/ directory and a benches/ directory, but nothing in the README describes how you would distribute or consume a Scryer library written by someone else. If your project depends on a broad set of community packs, that dependency is not addressed here, and you should treat it as unverified rather than assume parity with larger systems.
Finally, the toolchain floor is real. rust-version = 1.93.1 in Cargo.toml, edition 2024, and the README's warning that distribution Rust packages lag behind together mean that a locked-down build environment with an older compiler will not build this crate. That is a constraint on the environment, not a defect in the code, but it decides adoptability in some organizations.
Scryer Prolog compared with SWI-Prolog and Trealla Prolog
The honest comparison point is SWI-Prolog, which appears in the related searches alongside Scryer. SWI-Prolog is the default Prolog for most working programmers, and its distinguishing property is breadth: a large set of bundled libraries, a pack system, and integrations that people reach for without thinking. Scryer's distinguishing property is different. It is a from-scratch WAM implementation in Rust that follows a published reconstruction, with conformance to specific ISO test suites stated as a measured result, and with clp(B), clp(ℤ), DCGs, attributed variables, delimited continuations and tabling designed into the same binary rather than bolted on. If your question is "which Prolog has the library I need," the answer is usually not Scryer. If your question is "which Prolog can I embed in a Rust program and reason about from the standard up," Scryer is built for that.
Trealla Prolog is the other name in the search data, and the difference in approach is visible from the outside: Trealla is a compact C implementation, which makes it small and easy to drop into environments where a Rust toolchain is unwelcome. Scryer's bet is the opposite one. Writing the system in Rust buys memory safety in the engine, a build system that produces both a binary and a linkable library, and a codebase that a Rust programmer can read. It costs a compiler version floor and a longer build. Neither choice is free, and the right pick follows from which cost you would rather pay.
The related searches also include scryer prolog wasm and scryer prolog python. Nothing in the README describes an official WebAssembly build or a Python binding, so treat both as unconfirmed. The crate does expose a cdylib, which is the mechanism an FFI-based binding would use, but the README does not document a Python package.
Maintenance, licensing, and what an upgrade actually costs
The repository is not archived, and the last push was on 2026-09-19, which places it within the last two weeks. Release cadence is uneven rather than steady: v0.10.0 is dated 2025-09-27, v0.9.4 is dated 2024-02-29, and v0.9.3 is dated 2023-11-02. Between v0.9.4 and v0.10.0 there is a gap of roughly nineteen months, so a pinned release can sit unchanged for a long time while master moves. If you vendor a release, plan for the possibility that the next one is far away, and read the commit history rather than the release list if you need to know what changed recently.
Licensing is BSD-3-Clause, stated in both the README's repository metadata and the license field of Cargo.toml. That is a permissive licence with a three-clause structure, which in practice means you can redistribute and modify the code provided you keep the copyright notice and the disclaimer and do not use the project's name to endorse your derivative. The README does not include the full licence text or a list of third-party dependency licences, and the dependency tree includes crates such as ring and native-tls that carry their own terms. If you ship a binary, check those separately. Nothing here is legal advice.
The upgrade cost is dominated by the toolchain, not the API. Because rust-version is pinned at 1.93.1 and CI validates that value, moving to a new Scryer release may require a newer Rust than your build image has. The --locked flag in the documented cargo install command exists precisely to keep dependency resolution stable across installs, so use it. If you build from a checkout, the Dockerfile's cargo-chef staging is the model to copy: separate dependency compilation from source compilation so that a Scryer version bump does not rebuild the entire dependency graph.
Editorial conclusion
Adopt Scryer Prolog if you want an ISO-conformant Prolog with clp(B), clp(ℤ), DCGs, attributed variables and tabling in one binary, and you are willing to build it with Rust 1.93.1 or newer. Do not adopt it if you depend on a large third-party pack ecosystem or on the WAM JIT and precise compacting GC that the README still lists as unfinished. Before committing, run the dif/2 and variable_names/1 test suites the README names against your own workload, and check the package.rust-version key in Cargo.toml against your toolchain.
Frequently asked questions
How do I install Scryer Prolog?
Three routes are documented: precompiled binaries from the releases page, cargo install --locked --git https://github.com/mthom/scryer-prolog.git, or cloning the repository and running cargo build --release, which places the binary in target/release.
Which Rust version does Scryer Prolog need?
The README points to the package.rust-version key in Cargo.toml, where the value is 1.93.1, and notes that CI validates the accuracy of that number. It also warns that Rust packages shipped by Linux distributions and Macports tend to lag behind what Scryer uses.
Does Scryer Prolog conform to the ISO Prolog standard?
The README states that Scryer passes all tests of syntactic conformity, of variable_names/1, and of dif/2, linking to Ulrich Neumerkel's conformance test pages for each.
Does Scryer Prolog compile Prolog to native code?
No. Phase 3 of the README describes using the WAM code from the code generator to get JIT-compiled and executed programs, and says the question of how to get assembly from WAM code is still being considered.
What does \+ do in Prolog?
The README does not document the \+ operator, so this cannot be answered from the available material. Scryer does implement dif/2 as a sound constraint, which is a different mechanism from negation as failure.
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/mthom-scryer-prolog)