AI can produce code faster than a person can review it. That moves the bottleneck. Getting a plausible function onto the screen is cheap. Establishing what it can touch, how it behaves when the world goes wrong, and whether an edit changed anything meaningful still takes careful review.
Jacquard is a research programming language built around that job. A function's type shows what it may ask the outside world to do. The same program can run against real services, recorded events, or simulated failures. Code identity ignores formatting, comments, and ordinary renames.
Probability and exhaustive branching use the same effect-handler machinery. They do not require a separate testing or modeling language.
What's borrowed, what's combined
Jacquard borrows from algebraic-effect languages such as Koka, Eff, Effekt, and Frank; from capability systems; from probabilistic systems such as Gen and Pyro; and from content-addressed systems such as Unison and Nix. None of those ideas began here. The experiment is to combine them around one problem: reviewing and approving code produced faster than a person could have written it.
Working with models on a new language
I used coding models while developing the compiler, runtime, standard
library, documentation, and test suite. There was no pre-existing
Jacquard corpus for the models to imitate. With a self-contained SKILL.md, repository context, executable tests, a
small kernel, and a tight checker loop, they could still contribute
and write public-syntax programs. Their recurring mistakes are
familiar-language guesses: imports, field accessors, infix arithmetic,
string interpolation, and handler behavior Jacquard does not provide.
The checker catches effect-row mismatches and ill-typed resumption
calls. Properties, replay, and exhaustive tests catch programs that
type-check but make the wrong decision.
Effects appear in the type
Ordinary code review often requires reconstructing possible effects from implementation and context. Jacquard puts those effects in function types. This policy body asks for three telemetry values, and its signature exposes that requirement:
effect Telemetry where {
inventory-health : () -> Health
payments-health : () -> Health
error-spike? : () -> Bool
}
release-assessment : () ->{Telemetry} Assessment
release-assessment() = {
let inventory = inventory-health()
let payments = payments-health()
let spike = error-spike?()
Assessment(inventory, payments, spike,
decide(inventory, payments, spike))
} {Telemetry} shows the effects this function may perform
at this layer. It may ask for telemetry, but it cannot directly use the
network or filesystem. Higher-order functions carry effects from the
functions they receive, and handlers remove only the effects they
handle.
Once handlers are chosen, any world effects left at the root are the
program's authority requirements. Network and filesystem
effects require explicit --allow grants, for example jac run policy.jac --allow net --allow fs. If execution reaches an ungranted effect, it stops with a
diagnostic. The checker can compare inferred requirements with an
expected manifest without running the program.
The threat model is accidental or unnoticed authority growth in generated code. A whole-network grant does not stop a malicious program from using that network access, and 0.1 has no host allowlists or path-scoped grants. There is no user-facing general C FFI in 0.1. Language-level checks still belong inside an operating-system sandbox when the code is untrusted.
One policy, three passes
The installed release-risk demo shows the central workflow. It prints the policy's inferred requirement, runs the policy against one concrete telemetry snapshot, calculates the probability of each release decision conditioned on a failed checkout, and asks Warp to verify the safety rule across all 18 modeled telemetry worlds.
$ sh ~/.local/share/jacquard/demos/case-studies/release-risk/run.sh
== inferred authority ==
release-assessment : () ->{Telemetry} Assessment
== the same policy under a concrete snapshot handler ==
assessment(healthy, degraded, false, canary(5))
== the policy under a probabilistic telemetry handler ==
0.305077 canary(5)
0.295394 hold("inventory-down")
0.184621 canary(10)
0.155903 hold("payments-down")
0.059005 ship
== Warp: exhaustive proof over all 18 telemetry worlds ==
PASS a down service is never approved to ship
(verified exhaustively (18 cases))
3 passed, 0 failed, 0 skipped, 0 refused The transcript is shortened here, but its values and test result are pinned in the release-risk demo and command-line test suite. Every major release claim has a corresponding test, negative case, and stated caveat in the 0.1 claim matrix.
One program, several worlds
An effect describes a request. A handler decides how that request is answered. The production handler can call a real service. Another handler can return a script, replay recorded interactions, or model weighted outcomes. The requesting program stays the same. In the demo, one handler supplies today's telemetry snapshot and another supplies a probability model after a failed checkout. This lets a reviewer test policy under outage, stale-data, and hostile-input worlds before connecting it to production resources. A production run still needs explicit permission for any world effects left after its handlers are installed.
Probability uses the same machinery
Jacquard represents finite uncertainty through a regular
Dist effect. Programs choose among weighted options and
record evidence. A handler chooses how to calculate the result. Exact
enumeration visits every reachable outcome for a finite model within
the configured budget. Seeded likelihood weighting samples when full
enumeration is too expensive.
Under the hood, a multi-shot handler resumes the rest of a computation once for each branch and combines the results. The current implementation has no continuous distributions, gradients, or general-purpose probabilistic optimizer.
Warp tests the program in place
Warp is Jacquard's test framework. Pure cases and seeded properties are deterministic and cacheable. World tests are separate and require explicit grants. Strict replay fails when a program's requests drift from recorded interactions. Tests can swap handlers instead of building a mocking layer, and fault handlers explore failures at effect boundaries.
An exhaustive property can run every supported fault path within a budget. Warp's cache follows resolved dependencies: formatting and comments do not rerun a pure test, while a structural dependency change invalidates its tests.
Code identity survives harmless edits
Jacquard definitions are addressed by a SHA-256 hash of canonical, resolved structure. Formatting, comments, provenance, and ordinary local or term renames are removed before hashing. An edit that changes resolved structure changes the hash. This supports structure-aware diffs and exact build caches. The claim is narrow: equal hashes mean equal canonical structure under the current serialization rules, not proof that arbitrary programs behave the same.
A working native compiler
Public programs use the compact .jac syntax. They lower
to a 27-form kernel shared by the checker and interpreter. The
implementation includes an OCaml type-and-effect checker, a CPS
interpreter, a Jacquard-written standard library, the command-line
tool, Warp, and a native ahead-of-time backend.
The native backend emits C, specializes reachable definitions, and
caches compiled units by content hash. Native and interpreted runs
are checked against each other under clang and gcc. Public
.jac programs and kernel .jqd programs share
the same semantics, but the build command currently takes
the serialized kernel carrier directly. Wiring surface parsing into
that command remains open work. The benchmark programs below use the
kernel carrier and pass the interpreter/native differential tests.
Performance is not Jacquard's main claim. These measurements establish that the backend runs substantial programs at plausible speed. The table is a subset of a July 6 run on a Ryzen 9 7950X3D: median of five wall-clock runs per cell, with measured engine startup subtracted. The C column is raw, so its process startup remains included.
| Program | Jac interpreter | Jac native (clang 18) | Python 3.11 | Hand C |
|---|---|---|---|---|
| fib | 726 ms | 4 ms | 71 ms | 3 ms |
| sort | 67,728 ms | 96 ms | 262 ms | 25 ms |
| sum | 13,922 ms | 54 ms | 62 ms | 23 ms |
| text | 182 ms | 10 ms | 10 ms | 5 ms |
| state loop* | 24,181 ms | 159 ms | 76 ms | 3 ms |
| code mutation* | 2,558 ms | 4 ms | 9 ms | 2 ms |
Native compilation cuts these interpreter times by roughly 18 to 700 times. On the specific benchmark twins, native Jacquard is faster than Python on fib, node-based merge sort, list sum, and the task-equivalent code-mutation case; the text test has the same measured median as Python. Handled state is slower than Python method calls because it pays for the handler and continuation machinery rather than a direct method dispatch.
* State loop and code mutation are task-equivalent comparisons: C and Python use their native mechanisms rather than Jacquard's handler or code-value representation. The full benchmark record includes gcc, methodology, variation, and the limits of each comparison.
What exists, and what does not
Jacquard Core 0.1 works end to end as a release candidate. Published binaries cover Linux x86-64, macOS Intel, and macOS Apple Silicon. The repository includes executable demos, a claim matrix tied to tests, and a separate limits document.
The current boundary matters:
- The surface syntax is usable and still evolving.
- There is no language package manager or public registry yet.
- The interpreter and native runtime are single-threaded.
- Root grants cover whole effects rather than paths, hosts, or quotas.
- Probability is finite and discrete.
- The checker and runtime have extensive tests, but no formal soundness proof or security audit.
Package management, editor tooling, direct surface-to-native builds, runtime optimization, and ordinary language conveniences remain open work. I expect the syntax to change as people use it.
Jacquard is licensed under the Apache License 2.0. Programs written and compiled with Jacquard can use any license their authors choose.
Try a small program
The release installer does not require OCaml or opam. It downloads a checksum-verified binary, the prelude, demos, and the native runtime:
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 second command prints 120. For coding agents, start
with docs/SKILL.md. It contains the syntax, command
reference, testing model, and common mistakes in one file.
To inspect the archive before running anything, download it and its checksum from the release page. For Linux x86-64:
VERSION=jacquard-core-0.1-rc3
TARGET=linux-x86_64 # or macos-arm64 / macos-x86_64
BASE=https://github.com/jbwinters/jacquard-lang/releases/download/$VERSION
curl -fLO "$BASE/jacquard-$TARGET.tar.gz"
curl -fLO "$BASE/jacquard-$TARGET.tar.gz.sha256"
if command -v sha256sum >/dev/null 2>&1; then
sha256sum -c "jacquard-$TARGET.tar.gz.sha256"
else
shasum -a 256 -c "jacquard-$TARGET.tar.gz.sha256"
fi
tar -tzf "jacquard-$TARGET.tar.gz"
After verification, unpack the archive and inspect its packaged
README before copying bin, libexec, and
share into your chosen prefix.
The name comes from the Jacquard loom, whose punched cards helped turn weaving into programmable control. Warp is the test framework. That part was too apt to leave unused.
The useful test now is small and concrete: ask an agent to write one effectful policy, one handler, and one Warp property. Reports about confusing syntax, missing library pieces, weak diagnostics, and places where an agent confidently writes the wrong thing will shape the next release.