A workbench where people and agents do engineering work in one recorded workspace.
zag is a terminal, a block model, an agent runtime and a standards control plane in one Zig program. It fetches no package from the network: the whole thing builds from the Zig standard library.
Status: the substrate is built and tested, and an agent loop runs against it with every tool call decided separately. The graphical renderer and the editor surfaces are not written yet, and answers do not stream.
zag doctorprints what this build can and cannot do, so the claim never runs ahead of the code.
The usual mistake is to make the terminal grid the application's data model. Then the interface owns the truth. Everything else — history, replay, audit, remote attachment, agent context — has to be added back later. Each arrives as its own feature, and each can disagree with the others.
Here the workspace event stream owns the truth:
- The interface does not own truth. It is a fold over the log.
- Agents do not own truth. They propose typed requests; the log records what
happened.
zag askwrites its whole run into the same log a command goes into, refusals included. An agent run and a shell command read the same way afterwards. - The pseudoterminal does not own truth. It produces bytes, which become events.
Everything else follows from that. A block list, a session tab, an execution graph, an audit trail and an agent's context are all views of the same events.
| Part | What it does |
|---|---|
src/events |
The typed event union, append-only hash chain, immutable content-addressed output store, the causal graph and the derived dependency graph |
src/workspace |
Blocks, sessions, workflows, structured history, and the workspace service |
src/editor |
The command line as an editing document, with undo that groups by intent |
src/terminal |
Escape-sequence parser, screen with scrollback, shell integration, real pseudoterminal, and the recording terminal |
src/ai |
Capabilities, the policy engine, the workspace policy file, approvals, typed tools and their executors, kernel-enforced path containment, the model connectors and the gate they pass through, the agent loop, attention selection, risk, impact, transparency, generated cards |
src/language |
The plain-language pass, with controlled-English and easy-to-read profiles |
src/knowledge |
The concept system, the thesaurus view, the published vocabulary and the workspace knowledge base |
src/metadata |
The registry that stops one field having four names |
src/standards |
The standards registry, conformance profiles, crosswalks and the evidence ledger |
src/content |
The typed content model and its publishers |
src/accessibility |
The semantic tree, contrast checks and the accessibility statement |
src/reports |
The metric registry and one report notation |
zig build test # run every test
zig build # build the tools
zig build check # run the tests, then audit this repository
zig build emit # regenerate the schemas, the vocabulary and llms.txt
zig build bench -Doptimize=ReleaseFast # measure the hot paths
You need Zig 0.16.0.
zag term # a shell in a terminal that records what you do
zag doctor # what this build can and cannot do
zag policy # the policy in force, and where it was read from
zag providers # the model connectors, and which credentials are set
zag ask "why did that fail?" # ask a model; it can use tools, one decision each
zag ask --stream "..." # the same, printed as the answer arrives
zag secrets .env # what would be taken out before anything is recorded
zag why .workspace/events.jsonl # what a failure depended on, and what it affected
zag run -- zig build test # run a command and record it as a block
zag shell-hook bash # the shell integration to add to your shell
zag workflow # this repository's own workflow, as a task graph
zag history "status:failed zig" # search recorded work, not a text file
zag knowledge # the knowledge under .workspace/, and what is overdue
zag objects --root . # audit stored command output without changing it
zag recover --root . # inspect a damaged log and print a recovery plan
Settings live in .workspace/settings.toml. zag-audit emit writes an example with
every value at its default. A setting this build cannot read is reported by
name, with what was found and what is being used instead, and the terminal
opens anyway — a mistake in that file never costs you a shell.
Two steps. Set a key, then write a policy:
export ANTHROPIC_API_KEY=... # or any connector; run "zag providers"
zag policy --init # writes .workspace/policy.toml
zag ask "why did the build fail?"
zag doctor says which of the two is missing. If a key is set but no policy
allows reaching the provider, it names the host and tells you what to run —
that is the case where nothing is broken, nothing is misspelt, and the only
symptom is a refusal at the moment of asking.
With no policy file the built-in one is in force: it allows a model running on your own computer and nothing else. So if you use Ollama, none of this is needed.
.workspace/policy.toml is a list of rules. Each [[rule]] names one
effect — allow, ask or deny — and lists the capabilities it applies to:
[[rule]]
id = "ask-a-model"
allow = ["model.infer"]
because = "This workspace may ask a model questions."
[[rule]]
id = "reach-the-provider"
allow = ["network.connect"]
hosts = ["api.anthropic.com"] # scoped: nowhere else may be reached
because = "The model runs there."
[[rule]]
id = "run-commands"
ask = ["process.execute"] # stops for a person, each time
because = "A person decides each command before it runs."The effect is the key, not a value: it is allow = [...], not
effect = "allow". because is required and is what a person is shown when a
decision is made. A rule may be scoped by hosts, paths or agents; an
unscoped rule applies to every resource of that capability.
Anything no rule allows is refused. A file with a mistake anywhere in it is
refused whole — nothing is granted by being written badly — and zag policy
says which rule and why.
Capabilities: fs.read, fs.write, fs.delete, process.execute,
process.signal, network.connect, network.listen, git.read,
git.commit, git.push, credentials.use, credentials.read, mcp.invoke,
container.start, remote.execute, model.infer.
zag-audit is the second binary. It checks a repository against the standards
it claims to meet, and nothing it does is needed to record work:
zag-audit check # audit this repository; the release gate
zag-audit lint README.md # check text against the plain-language rules
zag-audit terms workspace # what a word means here
zag-audit standards # the standards in force, and their editions
zag-audit emit # regenerate the schemas, vocabularies and docs
zag-audit evidence # the conformance statement, from recorded evidence
zag-audit card model # the model card, generated from the system
zag-audit accessibility # the accessibility statement and the themes
zag-audit lifecycle # the lifecycle record, and what has not started
zagd holds a workspace open for clients, remote people and background agents:
zagd status # what is in the workspace
zagd verify # check the event log and stored command output
zagd plan # what each step of a workflow would need
zagd history "branch:main" # the same search, without the tool
Sixty-five standards, specifications and frameworks are recorded in
standards/registry. Each carries its edition, its status and how the workbench
enforces it. That record is not decoration: the build reads it, and refuses a
registry that enforces a withdrawn or draft edition.
The rules that a program can check are checked by the build:
- Plain-language rules over the product's own text, including this file and the tool's own help.
- Terminology rules over the product's own vocabulary. A circular definition or a term that means two things fails the build.
- Metadata rules over every field that crosses an interface.
- Contrast and target-size rules over the shipped themes and the accessibility tree the renderer must publish.
- Risk rules: a risk that claims to be mitigated must name a control that is enforced by code. An instruction to a model is not a control.
- Knowledge rules over
.workspace/: an entry needs a named owner, a summary and a review date, and it cannot claim to be about a concept nobody defined.
The rules that a program cannot check are named as such, in every report:
- Whether a reader can find, understand and use the information.
- Whether a person using a screen reader can finish a task.
- Whether a risk treatment works in practice.
Those are settled by evaluating the product with people, and by audit. The workbench never reports a score that implies otherwise. There is no "ISO compliant: 93/100" anywhere in it, and there never will be.
An agent asks; the local policy decides; the decision becomes a record.
request -> plan -> typed tool request -> policy decision
-> (a person, when the policy says so) -> execution -> events
- There is no free-form shell tool. Each request names one capability and one resource.
- A path is normalised before policy matching, so textual
..traversal is rejected. Beyond that, the executors open every file through a workspace directory handle withRESOLVE_BENEATHandRESOLVE_NO_MAGICLINKS, so the kernel refuses a symbolic link that leaves the workspace rather than the program noticing afterwards. Event logs, objects and recovery evidence also reject a symbolic link in the final path component. - A command runs from its argument vector. There is no shell between the two, so there is nothing for a quotation mark to escape into.
- An executor spends the decision it was handed. It re-derives the capability and the resource from the request and refuses unless both match, so a decision to read one file cannot be spent on another.
- Asking a model is three permissions, not one: using a model, reaching that host, and spending that credential. All three are decided before the request is encoded, so a refused request is never built and a refused credential is never read.
- A model cannot name a capability. Its tool call becomes a typed request or nothing at all, and the capability comes from the request kind. Text can make a model ask for anything; asking is all it can do.
- Two tools are never offered to a model: asking another model, which would spend a credential on a request nobody read, and starting an agent, which would let it widen its own reach.
- The policy is a file the person writes, in
.workspace/policy.toml. It is never shown to a model and never consulted by one. Runzag policyto read it in words. A file that does not parse allows nothing; nothing more permissive is substituted for it. - An operation that cannot be undone stops and asks, in words that name the operation and its consequence.
- A repository instruction file shapes behaviour. It can never grant a capability, and the checker reports any line that tries.
docs/if-something-is-wrong.md is for anyone affected by work done with zag,
whether or not they use it. It says how to read the record, how to raise a
problem, and what this project can and cannot do about it.
docs/architecture.md— the event graph, the block model and the control planedocs/standards-conformance.md— which standards apply and how each is checkeddocs/plain-language.md— how ISO 24495 is applied, and what a checker cannot decidedocs/competitive-position.md— how zag compares with other terminals, and what it cannot do yetdocs/roadmap.md— what is complete, what happens next, and the evidence each milestone needsdocs/threat-model.md— trust boundaries, implemented controls and residual security workdocs/platform-support.md— compile evidence, runtime evidence and explicit platform exclusionsdocs/adr/— why the architecture is the way it isAGENTS.md— how to work in this repositoryCONTRIBUTING.md— how to prepare and check a changeSECURITY.md— how to report a vulnerability without publishing exploit detailsllms.txt— the machine-readable index
MIT. See LICENSE.