@arxo/cli
The law command of Arxo Law. Write a canon (a law, a tariff, a standard,
a rulebook) as a package, check it, test it, pin it into a case and ask the
case a question. Every answer is a canonical evaluation document with a
proof and hashes; law eval replays it offline to the same bytes.
Install · Write a canon · Ask a case · Commands · Related packages
Install
| Route | Command | Platforms |
|---|---|---|
| npm | npm i -g @arxo/cli | macOS arm64, Linux x64 |
| Homebrew | brew install arxohq/tap/law | macOS arm64, Linux x64 |
| Shell script | curl -fsSL https://github.com/arxohq/law-releases/releases/latest/download/install.sh | sh | macOS arm64, Linux x64 |
| APT | package arxo-law, setup at packages.arxo.io | Debian, Ubuntu (amd64) |
| Archive | GitHub Releases with .sha256 next to each archive | macOS arm64, Linux x64 |
All routes carry the bytes of the same GitHub Release. This npm package is a
thin launcher: the platform package @arxo/cli-<os>-<arch> holds the binary,
and law version --json prints its sha256.
$ law version
law 0.1.1
semantics: law.core/0.2
std for language 0.2: 0.2.0
lawql: lawql/1 (queryResult 0.1)
binary hash: sha256:cfa7c17232f2…
Write a canon
The session above, from an empty folder: a parcel tariff — up to 2 kg the fee
is 500, above that 500 plus 150 for every kilogram over 2. law init --template package creates law.toml and source.law; the rules go into
source.law:
language "law.core" version "0.2";
package demo.parcel_tariff version "0.1.0";
namespace "urn:law:demo:parcel_tariff";
pub entity Shipment { label en unofficial "Shipment"; }
pub relation weight_kg(s: Shipment, kg: Decimal) kind empirical {
label en unofficial "weight of the shipment, kg";
}
pub relation fee(s: Shipment, amount: Decimal) kind institutional {
label en unofficial "postage under the tariff";
}
rule BaseFee(s: Shipment, kg: Decimal) strict {
label en official "up to and including 2 kg: base fee 500";
when weight_kg(s, kg);
when kg <= 2.0;
then fee(s, 500.0);
}
rule HeavyFee(s: Shipment, kg: Decimal) strict {
label en official "over 2 kg: 500 plus 150 for each kilogram above 2";
when weight_kg(s, kg);
when kg > 2.0;
then fee(s, 500.0 + (kg - 2.0) * 150.0);
}
Expectations are written from the tariff text before the run: 5 kg →
500 + 3 × 150 = 950; exactly 2 kg → 500. tests/tariff.lawtest:
language "law.core" version "0.2";
package demo.parcel_tariff version "0.1.0";
namespace "urn:law:demo:parcel_tariff";
test "urn:query:demo-parcel-tariff-t01-heavy" {
given {
context { legal_time @2026-09-25; decision_time @2026-09-25T00:00:00Z; knowledge_time @2026-09-25T00:00:00Z; timezone "UTC"; }
assert "w": weight_kg(entity_ref("urn:case:box-1"), 5.0) { origin case_input; }
}
evaluate truth(fee(entity_ref("urn:case:box-1"), 950.0));
expect truth_status == TRUE_ONLY;
expect evaluation_status == COMPUTED;
}
test "urn:query:demo-parcel-tariff-t02-base" {
given {
context { legal_time @2026-09-25; decision_time @2026-09-25T00:00:00Z; knowledge_time @2026-09-25T00:00:00Z; timezone "UTC"; }
assert "w": weight_kg(entity_ref("urn:case:box-2"), 2.0) { origin case_input; }
}
evaluate truth(fee(entity_ref("urn:case:box-2"), 500.0));
expect truth_status == TRUE_ONLY;
expect evaluation_status == COMPUTED;
}
and in law.toml:
[[tests]]
family = "parcel_tariff"
suites = ["tests/tariff.lawtest"]
world = ["demo.parcel_tariff"]
law engine check . is the static check: types, names, the header against
the manifest. A misspelled relation is reported with its line, column and a
stable code (LDC-E2102), so an editor or CI can react to the code, not to
the wording. law test runs the declared scenarios.
Ask a case under it
A case package holds your situation; the canon comes in as a pinned
dependency. law pack puts the canon into one portable .arxo file, and
law add pins it in law.lock without any network. The case,
main.lawcase:
language "law.core" version "0.2";
package my_case version "0.1.0";
namespace "urn:law:my_case";
case Main {
context {
legal_time @2026-10-01;
knowledge_time @2026-10-01T12:00:00Z;
decision_time @2026-10-01T12:00:00Z;
timezone "UTC";
}
assert demo.parcel_tariff::weight_kg(entity_ref("urn:case:box-1"), 5.0) { origin case_input; }
}
law ask --out runs/fee saves the request and the full evaluation document;
law eval runs/fee recomputes it and gets the same result hash. Without
jq, --format brief prints a one-line JSON summary.
Commands
law --help lists every flag. The main ones:
| Command | What it does |
|---|---|
law init <dir> [--template case|package] | a new case package (your situation) or canon package (your rules) |
law add <name>@<version> · law add <file.arxo> | pin a dependency in law.lock and install its bytes into deps/ |
law install [--offline] | restore deps/ from law.lock |
law update <name>[@<version>] [--replay <dir>] | move a pin; --replay shows which saved answers would change |
law outdated | what is pinned, what is published; the lock is untouched |
law test | run the scenarios declared in law.toml |
law ask (--query … | --query-json <file> | --card <id>) | ask a case; --out <dir> saves the request and the evaluation document |
law eval <dir | file.arxo> | replay a saved evaluation offline; from a container, check it against the saved documents |
law case questions · check · facts · document · diff | work with a case: question cards, facts with provenance, attached documents |
law pack --out <file.arxo> · law unpack · law inspect | one portable container: packages, lock, inputs; expand or inspect it |
law key new · law sign · law publish | sign a container; publish to a registry directory |
law audit | formalization measure of a package; executes no cases |
law types <package> | TypeScript declarations of a package |
law serve --world <dir> | an HTTP service over a pinned world: POST /v1/ask returns the same document |
law engine check · lock · … | low-level engine commands: static check, own lock, and more |
law version [--json] | tool version, semantics lines, hash of the binary |
Related packages
@arxo/law: the same engine in Node and the browser — ask a pinned canon from JavaScript or TypeScriptcreate-arxo: a ready TypeScript project,npm create arxo@latest my-app- Guides: quickstart · reading an answer
Apache-2.0.