Show HN: Jacquard, a programming language for AI-written, human-reviewed code
Jacquard is a research prototype programming language designed for AI-written, human-reviewed code. It features built-in effect tracking, probabilistic programming, and content-addressed identity, allowing human reviewers to understand a program's reach and certainty without reading every line.
Notifications You must be signed in to change notification settings
Fork 0
Star 1
BranchesTags
Open more actions menu
Folders and files
NameName
Last commit message
Last commit date
Latest commit
History
139 Commits
139 Commits
.github
.github
bench
bench
bin
bin
corpus
corpus
demos
demos
docs
docs
prelude
prelude
runtime
runtime
scripts
scripts
spec
spec
src
src
test
test
.env.example
.env.example
.gitignore
.gitignore
.ocamlformat
.ocamlformat
.tool-versions
.tool-versions
AGENTS.md
AGENTS.md
CONTRIBUTING.md
CONTRIBUTING.md
LICENSE
LICENSE
NOTICE
NOTICE
README.md
README.md
RUNTIME-EXCEPTION.md
RUNTIME-EXCEPTION.md
TRADEMARKS.md
TRADEMARKS.md
dune-project
dune-project
jacquard.opam
jacquard.opam
Repository files navigation
Jacquard is a research prototype for running, reviewing, simulating, and trusting programs written by models and reviewed by people.
Concretely, it is a small programming language with a compact .jac surface syntax, an OCaml checker and CPS interpreter, a C-emitting native AOT backend that currently compiles the kernel .jqd carrier, a command-line tool, a Jacquard-written standard library, and a test framework called Warp. Version 0.1 works end to end but is a research prototype, not a production language; docs/release/0.1/LIMITS.md is the honest boundary.
Install the 0.1 release candidate without OCaml or opam:
curl -fsSL https://raw.githubusercontent.com/jbwinters/jacquard-lang/jacquard-core-0.1-rc3/scripts/install.sh | sh ~/.local/bin/jac run ~/.local/share/jacquard/demos/basics/m1-fact.jac
The expected output is 120. Linux x86-64, macOS Intel, and macOS Apple Silicon binaries are published; development from source is documented below.
Then run one policy under concrete and probabilistic telemetry worlds, followed by sampled and exhaustive Warp checks:
sh ~/.local/share/jacquard/demos/case-studies/release-risk/run.sh
For Humans
Most languages tell you what a program computes. Jacquard also exposes which effects it may perform, finite discrete uncertainty, and canonical program identity. Tools can inspect all three because they live in the language rather than only in comments, logs, or your memory of the codebase.
Things you can do here that most languages cannot offer:
Read one line and see the effects a function may perform. A signature like (text) ->{net} text says the function may perform the net effect. The Jacquard runtime rejects unhandled world effects unless their authority is explicitly granted with --allow, including effects performed by dynamic code. This is language-level enforcement in a research runtime, not a substitute for an operating-system sandbox.
Run one program against many worlds. The same code can run against the real network, a scripted fake, a recording of last week's traffic, or a probability model of how servers usually behave. A handler is the piece that answers a program's requests to the outside world; you swap the handler, and the code never changes. This can replace much conventional mocking at effect boundaries and makes "what would my agent do if the API went down?" an ordinary test.
Enumerate exact probabilities for finite discrete models. A program can sample weighted choices and record evidence, and enumeration lists every reachable outcome with its exact probability. The repair demo below treats a failing test as evidence and computes which patches remain possible and how likely each is.
Rename and reformat without changing canonical identity. Jacquard hashes canonical resolved structure rather than source bytes. Comments, formatting, provenance, and ordinary local or term renames are erased; pure tests rerun only when canonical code or dependency content changes. This is structural identity, not a proof that arbitrary programs are behaviorally equivalent.
The bet behind all of this: when most code is written by machines, the humans reviewing it need the language itself to answer "what can this touch, and how sure are we" without reading every line.
For Agents
Read docs/SKILL.md first. It compresses the kernel, the CLI, the prelude, Warp testing, and the known gotchas into one file, and it loads as a project skill from docs/SKILL.md. Operating rules are in AGENTS.md. What will save you time:
Behavior is pinned by evidence: cram transcripts under test/cli/, corpus goldens, demo scripts, and docs/release/0.1/CLAIMS.md. If a pin fails, treat it as information about your change, and never weaken a pin to make a diff pass.
The kernel is 27 forms (docs/ast.md); .jac is a projection onto those forms, and bootstrap .jqd remains permanently supported. Treat the shipped surface boundary and its parked follow-ups as release evidence, not as a frozen grammar; do not add out-of-scope features (AGENTS.md lists them).
The development gate is dune build @all && dune runtest && dune fmt followed by a clean git diff --exit-code.
Core Ingredients
For readers who speak programming languages:
One uniform representation: every form is a (head, meta, args) triple, and the kernel grammar has 27 forms. Quoted code is ordinary data.
Algebraic effects with deep, multi-shot handlers. A handler can resume a computation zero, one, or many times, which is what makes exhaustive search and exact inference ordinary library code.
Explicit capability grants. The runtime installs handlers for the outside world only for effects you pass with --allow; there is no ambient authority.
Type-and-effect rows. Every arrow carries the set of effects the function may perform, so a program's inferred row is its authority manifest.
Discrete probabilistic programming as a library: sample and observe are effect operations, and each inference algorithm is a handler.
Content-addressed definitions. Identity is a hash of canonical resolved structure with non-identity metadata erased, so formatting, comments, and ordinary local or term renames change nothing downstream.
Tooling that leans on the above: formatter, structure-aware differ, Warp tests with a content-addressed cache, record/replay, and a reproducible release evidence pack.
A native AOT path that emits C, specializes and caches units by content hash, and is differential-tested against the interpreter under clang and gcc.
The prototype is complete against its original core plan and has since added the public surface syntax, ringed standard library, Warp properties and cache, native compilation, packaged binaries, and product-scale case studies. The RC1 semantic boundary is pinned by 554 Alcotest/QCheck cases, 32 cram transcripts, 21 documentation examples, native sanitizer/leak/fuzz lanes, and a fresh-clone evidence workflow. RC2 repaired binary-demo packaging; RC3 adds an explicit runtime/output license exception and packages the native runtime. The current successor distribution relicenses Jacquard under Apache License 2.0 and keeps that runtime/output permission as an explicit clarification. These licensing and packaging changes do not change the language semantics pinned at RC1.
What It Looks Like
Here is one handler resuming one continuation twice. The block is copied byte-for-byte to test/docs-doctest/fixtures/readme-multishot.jac and run by the documentation test lane:
effect Choice where { choose : () -> Bool }
handle { match choose() { | True -> 1 | False -> 2 } } { | return x -> x | choose() resume continue -> add(continue(True), continue(False)) }
$ jac run test/docs-doctest/fixtures/readme-multishot.jac 3
The handler ran the rest of the program once with true and once with false, then collected both results. That ability to resume more than once is why exact Bayesian inference is a library handler here rather than a runtime feature. The repair demo builds on it: mutate a buggy program's quoted AST into candidate patches, treat a failing test as an observation, and read off the updated probabilities. Running candidate code is an authority, so the pure step still runs (it counts eight candidate patches) and then the demo refuses until you grant the rest:
$ jac run demos/tooling/repair.jac
8
error[E0814]: this program requires the eval effect, which is not granted (performed via posterior-over-patches)
hint: grant it with --allow eval, or handle the effect in the program
$ jac run demos/tooling/repair.jac --allow eval
Under the grant, one failing test leaves two surviving patches: the intended fix at 0.75 and a patch that games the suite at 0.25. Adding one regression test prunes the impostor, and the surviving fix prints as a one-line canonical diff: - sub + add. See sh demos/tooling/repair.sh for the full transcript.
Install A Release Binary
Most users do not need OCaml or opam. Install the reviewed 0.1 RC binary with:
curl -fsSL https://raw.githubusercontent.com/jbwinters/jacquard-lang/jacquard-core-0.1-rc3/scripts/install.sh | sh
The installer detects your OS and CPU, downloads the matching archive and SHA-256 checksum, refuses a checksum mismatch, and installs under ~/.local by default. Make sure ~/.local/bin is on PATH, then run:
jacquard --version jac --version
jac is the short alias for jacquard. Both commands set JACQUARD_PRELUDE from the installed package, so ordinary runs do not need an environment variable:
jac run ~/.local/share/jacquard/demos/basics/m1-fact.jac
Narrative demos ship with launchers that choose the installed binary and prelude automatically. They do not require Dune:
DEMO_ROOT="$HOME/.local/share/jacquard/demos" sh "$DEMO_ROOT/case-studies/release-risk/run.sh" sh "$DEMO_ROOT/worlds/agent-dream.sh" sh "$DEMO_ROOT/worlds/escrow/run.sh"
Use these launchers rather than directly running a probabilistic model or a multi-file entrypoint. The launcher selects infer where observation requires it and assembles related files in isolated scratch space.
To install under a different user-owned prefix:
curl -fsSL https://raw.githubusercontent.com/jbwinters/jacquard-lang/jacquard-core-0.1-rc3/scripts/install.sh \ | JACQUARD_INSTALL_PREFIX="$HOME/.jacquard" sh
Set JACQUARD_INSTALL_VERSION to install a different release tag. Supported binary targets are linux-x86_64, macos-x86_64, and macos-arm64; other platforms currently require the development setup.
Release archives are attached to jacquard-core-* GitHub releases. Each archive contains bin/jacquard, bin/jac, libexec/jacquard/jacquard, share/jacquard/prelude, share/jacquard/demos, the native C runtime, and the license, notice, exception, and trademark documents.
Development Quick Start
These commands assume a fresh clone and asdf available for installing opam. If you already have opam 2.5.x, start at the local switch step. If opam is already initialized on your machine, skip opam init.
git clone https://github.com/jbwinters/jacquard-lang.git cd jacquard-lang
asdf plugin add opam https://github.com/asdf-community/asdf-opam.git asdf install opam 2.5.1 asdf set opam 2.5.1 asdf reshim opam 2.5.1
opam init -y --no-setup --bare opam switch create . ocaml-base-compiler.5.1.1 -y eval "$(opam env)"
opam install --deps-only . --with-test --with-dev-setup --with-doc -y opam exec -- dune build @all opam exec -- dune runtest opam exec -- dune fmt git diff --exit-code
The switch step compiles OCaml 5.1.1 from source, so expect the first setup to take around ten minutes.
The final git diff --exit-code is part of the development contract: formatting must leave the worktree clean unless you intentionally commit the formatting diff.
Expected versions after setup:
opam 2.5.1 from .tool-versions
OCaml 5.1.1 from the repo-local _opam/ switch
dune, ocamlformat, alcotest, qcheck, digestif, menhir, cmdliner, odoc, utop, and ocaml-lsp-server from jacquard.opam
In a new shell inside an existing checkout, run:
eval "$(opam env)"
_opam/ is inten
[truncated for AI cost control]