A programming language for code that models write and people review.
When a model hands you a change, Jacquard answers three questions before you read a function body:
- What can this change touch? The checked signature lists every effect, and the runtime refuses any you have not granted.
- What will it do where you can't look? Run the same code against a snapshot, an exact probability model or every case.
- Is what I approved still what runs? An approval names a hash that survives reformatting and breaks on any real edit.
curl -fsSL https://raw.githubusercontent.com/jbwinters/jacquard-lang/jacquard-core-0.3.0/scripts/install.sh | sh
Installs Core 0.3.0 (7 October 2026) to ~/.local
on Linux x86-64 or macOS, with checksums verified. No OCaml needed.
New here? Read why a language, or the introduction on FriendMachine Research.
01 · what can this change touch?
The answer is on the first line of the diff.
A model edits a function that cleans up display names. In most languages, finding out whether the change can reach the network means reading everything it calls. In Jacquard the checker infers every function's effect row, and the row is part of the signature.
--- a/normalize.jac
+++ b/normalize.jac
@@ -1,3 +1,6 @@
-- Clean up a display name before it is stored.
-normalize-name : (Text) ->{} Text
-normalize-name(name) = text.trim(name)
+normalize-name : (Text) ->{Net} Text
+normalize-name(name) = text.trim(lookup-alias(name))
+
+lookup-alias : (Text) ->{Net} Text
+lookup-alias(name) = net.get(text.concat("https://aliases.example/", name)) $ jac check after.jac --print-sigs
lookup-alias : (Text) ->{Net} Text
normalize-name : (Text) ->{Net} Text
The new {Net} is not a comment the model chose to
write. The checker computed it from lookup-alias, and a
signature that left it out would not check. Until someone grants
network access, the runtime refuses to run the change:
$ jac run run.jac
error[E0814]: The program requires an effect that was not granted
Cause: This program requires net [world/high] — reach a network endpoint through the granted handler, which is not granted (performed via `normalize-name`).
Next step: grant it with --allow net, or handle the effect in the program
[exit status 3] This is language-level enforcement in a research runtime. It constrains Jacquard programs; it does not replace an operating-system sandbox.
02 · what will it do where you can't look?
Run the same code against worlds you cannot reproduce.
A release policy is written once against a Telemetry
effect. A handler answers the program's requests to the outside world.
An injected dependency is a handler that resumes the program once; a
Jacquard handler may also resume it never or many times. So the same
policy can run against today's readings, against an exact probability
model, and against every combination of readings.
multi effect Telemetry where {
inventory-health : () -> Health
payments-health : () -> Health
error-spike? : () -> Bool
}
-- A pure, reviewable release policy.
decide : (Health, Health, Bool) ->{} Decision
decide(inventory, payments, spike) =
match (inventory, payments, spike) {
| (_, Down, _) -> Hold("payments-down")
| (_, Degraded, _) -> Canary(5)
| (Down, Healthy, _) -> Hold("inventory-down")
| (Degraded, Healthy, _) -> Canary(10)
| (Healthy, Healthy, True) -> Canary(5)
| (Healthy, Healthy, False) -> Ship
}
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))
} A fixed snapshot
A handler that answers each reading from today's values.
assessment(healthy, degraded, false, canary(5)) An exact probability model
Given an observed checkout failure, which decisions could the policy have made, and how likely was each? Enumeration lists every one with its exact probability.
0.305077 canary(5)
0.295394 hold("inventory-down")
0.184621 canary(10)
0.155903 hold("payments-down")
0.059005 ship Every world, checked
Warp, Jacquard's test framework, checks the safety property in all 18 combinations of the readings instead of a sample.
PASS release-risk-suite/release risk/the concrete snapshot chooses a five-percent canary (1 check)
PASS release-risk-suite/release risk/the conditioned posterior is normalized with five decisions (2 checks)
PASS release-risk-suite/release risk/a down service is never approved to ship (verified exhaustively (18 cases))
3 passed, 0 failed, 0 skipped, 0 refused
Output of demos/case-studies/release-risk/run.sh from the
0.3.0 install, re-checked by
scripts/verify_examples.sh.
Walk through it →
03 · is what I approved still what runs?
An approval survives reformatting and breaks on any real edit.
Jacquard hashes the canonical resolved structure of each definition (SHA-256). Comments, layout and local names are erased, and every definition it calls is included by its own hash. An approval that names the hash survives an agent reformatting the code. Any structural change, in the definition or in anything beneath it, produces a new hash that needs a new approval.
greet(name) = {
println(text.concat("hello ", name))
text.length(name)
}
greet("reviewer") -- Same function: a comment, a new parameter name, a new layout.
greet(who) = { println(text.concat("hello ", who))
text.length(who) }
greet("reviewer") greet(name) = {
println(text.concat("hi ", name))
text.length(name)
}
greet("reviewer") | Version | Hash |
|---|---|
Originalgreet.jac | 451680d275e1 |
Reformatted, renamed, commentedgreet-reformatted.jac | 451680d275e1 |
Edited: says hi insteadgreet-edited.jac | 45cfe66faa1e |
Equal hashes mean equal canonical structure. They say nothing about whether two different programs behave alike.
04 · for agents
Built to be learned from one file.
SKILL.md covers installing Jacquard and writing, checking,
running, testing and compiling programs, and loads as a skill in coding agents.
Every diagnostic carries a stable code, a cause and a next step, also available
as JSON with
--diagnostic-format json-v1.
05 · in your application
Keep the decision in Jacquard and the I/O in your service.
Jacquard Host calls checked Jacquard functions from Python, TypeScript or Go. The function's effect row says which services the application must provide; you bind each effect to an ordinary object, and a missing one is refused before anything runs.
from jacquard_host import Runtime
class Warehouse:
def __init__(self, counts):
self.counts = counts
def on_hand(self, sku):
return self.counts.get(sku, 0)
program = Runtime().prepare("reorder.jac")
reorder = program.function("reorder", effects={"Stock": Warehouse({"bolt": 12})})
print(reorder("bolt", 40))
print(reorder("nut", 40)) 06 · the boundary
What 0.3.0 is, and is not.
- A research prototype with a checker, an interpreter, a native compiler via C, a standard library and the Warp test framework.
- No real network adapter ships; examples run against stubs, scripted responses, recorded traces and probability models.
- Exact inference is finite and discrete. Exhaustive checks are exhaustive only within their declared bounds.
-
Native binaries cover a documented subset: no dynamic
eval, interpreted tasks or typed channels. - No package manager, no formal soundness proof, no continuous distributions.
- The surface syntax is an evolving v0; future releases may not parse every program unchanged.