# Clara Rules: forward-chaining rules that read like the domain expert wrote them

> Clara is a forward-chaining rules engine for Clojure and ClojureScript with Java interoperability, built around developer-centric expert systems, where a rule is a defrule with pattern conditions and a conclusion rather than a separate artefact. It is published to Clojars, built with Leiningen, and ClojureScript tests run through puppeteer.

**oracle-samples/clara-rules** — Forward-chaining rules in Clojure(Script)

- Repository: https://github.com/oracle-samples/clara-rules
- Website: http://www.clara-rules.org
- Stars: 1,236 · Forks: 113
- Language: Clojure
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/oracle-samples-clara-rules

## What Clara is: a rules engine that is a library, not a framework

Clara is a forward-chaining rules engine written in Clojure or ClojureScript with Java interoperability, and it aims to simplify code with a developer-centric approach to expert systems. The phrase developer-centric is the important qualifier, because expert systems have a bad reputation and the usual reason is the authoring experience, with a separate rule language, a separate toolchain and a separate deployment story. Clara's answer is that a rule is just Clojure code, so the rules live in the same repository, use the same data structures as the application and are unit tested like any other function. It is a library rather than a framework, since the README describes it as being for use in an application rather than something that owns the application. The homepage is clara-rules.org, the licence is Apache 2.0, the primary language is Clojure, and the copyright is held by Oracle and its affiliates for 2018 and 2025.

## The example: records in, facts matched, conclusions printed

The README's example is a support request system and it shows the whole model in about thirty lines. You define records with defrecord, so SupportRequest with a client and a level, and ClientRepresentative with a name and a client. Then you define rules with defrule, a name, a docstring, pattern conditions in square brackets and a conclusion in the position after the arrow. The first rule, is-important, matches any SupportRequest whose level is :high and prints a message. The second, notify-client-rep, matches a SupportRequest and a ClientRepresentative joined on the ?client binding, and the comment in the source says Join via the ?client binding, which is the mechanism that makes two facts relate without a join condition written in SQL style. The level comparison uses the Clojure destructuring form with an equality test on a literal.

```clj
(defrule is-important
  "Find important support requests."
  [SupportRequest (= :high level)]
  =>
  (println "High support requested!"))
```

## The session, and the threading macro that makes firing look like a pipeline

The rules are run by building a session and firing it, and the README notes that you can just use Clojure's threading macro to wire things up. The chain starts with mk-session, then insert, which takes the facts, and fire-rules at the end. The facts themselves are constructed records, so (->ClientRepresentative "Alice" "Acme") and (->SupportRequest "Acme" :high). The printed output is the two println calls, first the high support requested line and then the notification that Alice has a new support request from Acme. The design point is that a session is an ordinary value in an ordinary pipeline, so inserting facts, firing and inspecting results are all ordinary function calls rather than a special API with a lifecycle.

```clj
(-> (mk-session)
    (insert (->ClientRepresentative "Alice" "Acme")
            (->SupportRequest "Acme" :high))
    (fire-rules))
```

## Forward chaining, and what that means for rule ordering

Forward chaining is the engine's fundamental choice and it explains a lot about how it behaves. In forward chaining, the engine matches the facts against the rule conditions, fires the rules whose conditions are satisfied, and the conclusions of those rules become new facts that can satisfy further rules, so the process continues until no more rules fire. That has a direct consequence for a developer, since the order in which rules are written can determine the order in which conclusions are derived, and a rule that matches a fact produced by another rule has to be considered in the right pass. The alternative, backward chaining, queries the goal and works backwards, and the two give different performance and predictability characteristics. The README does not belabour the difference, but the engine's identity as forward-chaining is the first thing to understand before writing rules that depend on each other, and the fact that a session is fired rather than queried is the visible consequence.

## ClojureScript and Java interop: the same rules, three runtimes

Clara runs on the JVM, in the browser through ClojureScript, and interoperates with Java. The practical value of the ClojureScript support is that a rule set written once can run client side, and the Java interop is what makes it usable in an existing JVM estate where the business rules need to talk to Java domain objects. The build reflects this, since ClojureScript tests are executed via puppeteer, which means the browser path is genuinely tested rather than merely compiled, and the package.json carries a single dev dependency on puppeteer. The other direction of interop, treating Java objects as facts, is the part that makes Clara usable without rewriting a Java codebase into Clojure records first, and it is the difference between a rules engine you adopt and one you migrate to.

## Building, testing and installing from Clojars

Clara is built, tested and deployed using Leiningen, which is still the build tool for the project, and the repository has a project.clj rather than a modern tools.deps setup. The ClojureScript test step needs a browser, and the README gives the two commands, npm install -g puppeteer and npx puppeteer browsers install chrome. The package.json confirms the shape, with puppeteer at version 22.11.2 as the only dev dependency. For use in a project, Clara releases are on Clojars, and you add the dependency, with the badge pointing at the latest version of com.cerner/clara-rules. The com.cerner group is a leftover from the project's origin at Cerner, and it is the coordinate you need when you add the dependency to a project.clj, so a reader following a newer tutorial that uses a different coordinate should check which one the release actually uses.

```bash
npm install -g puppeteer
npx puppeteer browsers install chrome
```

## The repository, the community and the state of the project

The top level of the repository is a conventional Clojure project with a few additions. There is src/ for the source, resources/, a project.clj, a package.json and a package-lock.json for the puppeteer setup, a .clj-kondo/ directory for the Clojure linter and a clj-kondo/ directory, a CHANGELOG.md, a CONTRIBUTING.md, a CONTRIBUTORS.md, a SECURITY.md describing the responsible disclosure process, a RELEASE.md, a NOTICE file and a LICENSE.txt. The communication channels are a Google Group for questions and a Slack channel on the Clojurians workspace, and the contributing section asks you to review the contribution guide before submitting a pull request. The last push to the repository was on 2026-04-27, the repository is not archived, and there are no GitHub releases, since the artefact is the Clojars artifact and the changelog is in the repository. The copyright line naming Oracle and its affiliates for 2018 and 2025 tells you the project has moved through corporate stewardship, which is worth knowing if you are deciding how much to rely on its future.

## Conclusion

Clara suits a Clojure team that wants to express business rules in the same language as the rest of the code, with a session model that makes the firing order visible, and that can run the same rules in Clojure and ClojureScript. It is the wrong choice if your rules are authored by non-programmers, since a rule is a macro invocation with destructuring, which is a code artefact rather than a document, and a poor fit for a JVM shop without Clojure, because the value of Clara is the embedding in Clojure's data model rather than the algorithm. Before adopting it, read the first steps guide on clara-rules.org, and note that the rules are compiled to session code at build time, so a rule change is a recompile rather than a data reload.

## FAQ

### What is Clara Rules?

It is a forward-chaining rules engine written in Clojure or ClojureScript with Java interoperability, aiming to simplify code with a developer-centric approach to expert systems. It is a library for use in an application rather than a framework that owns one, and it is published to Clojars under the Apache 2.0 licence.

### How do I write a rule in Clara?

With defrule, giving it a name, a docstring, pattern conditions in square brackets and a conclusion after the arrow. The conditions destructure facts, and facts that share a binding such as ?client are joined on that binding. The example matches a SupportRequest with a high level and a ClientRepresentative joined via the client binding.

### How do I run rules in Clara?

Build a session with mk-session, insert the facts and fire the rules, chained with Clojure's threading macro, so (-> (mk-session) (insert (->ClientRepresentative "Alice" "Acme") (->SupportRequest "Acme" :high)) (fire-rules)). A session is an ordinary value in an ordinary pipeline.

### Does Clara run in the browser?

Yes, through ClojureScript, and the ClojureScript tests are executed via puppeteer, so the browser path is tested rather than only compiled. The build needs npm install -g puppeteer and npx puppeteer browsers install chrome.

### How is Clara built and where do I get it?

Clara is built, tested and deployed using Leiningen, with a project.clj at the repository root. Releases are published to Clojars, and you add the dependency to your project from there. The repository also carries a SECURITY.md describing the responsible vulnerability disclosure process.

## Sources

- [Issues](https://github.com/oracle-samples/clara-rules/issues)
- [License: Apache-2.0](https://github.com/oracle-samples/clara-rules/blob/main/LICENSE)
- [oracle-samples/clara-rules on GitHub](https://github.com/oracle-samples/clara-rules)
- [Project website](http://www.clara-rules.org)
- [README](https://github.com/oracle-samples/clara-rules/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/oracle-samples-clara-rules
