Vyges CLI
vyges is the single command-line entry point to the Vyges hardware-IP toolchain.
It promotes a small set of tools and dispatches, git-style, to external
vyges-<name> binaries on your PATH:
| Command | Binary | What it does |
|---|---|---|
vyges | vyges | Top-level CLI: list modules, agent guide, bug/feature/sponsor |
vyges pdk-store | vyges-pdk-store | Consistent PDK presentation + resolution |
vyges catalog | vyges-catalog | Search and fetch IPs from the Vyges IP catalog |
All three binaries ship together in a single release, so installing vyges
installs the whole suite (see Installation).
This documentation is built from the CLI itself — the command reference pages are generated from each binary’s
--helpoutput.
Installation
Vyges is distributed as prebuilt binaries (the source is private). Every release
bundles all three binaries — vyges, vyges-pdk-store, vyges-catalog — and installs
them into ~/.vyges/bin.
These instructions describe the intended public install flow. The public release repo (
vyges-tools/cli) and Homebrew tap (vyges/homebrew-tap) go live with the first published release.
Homebrew (macOS / Linux)
brew install vyges/tap/vyges
This installs all three binaries in one shot.
curl installer (macOS / Linux)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/vyges-tools/cli/releases/latest/download/vyges-installer.sh | sh
The installer places the binaries in ~/.vyges/bin. Add it to your PATH if it isn’t
already:
export PATH="$HOME/.vyges/bin:$PATH"
Windows (PowerShell)
irm https://github.com/vyges-tools/cli/releases/latest/download/vyges-installer.ps1 | iex
The Vyges Loom engines (on demand)
The sign-off engines — the Vyges Loom suite — are not bundled with the CLI.
Fetch the whole suite when you want it, then invoke any engine through vyges:
vyges install loom # downloads the Loom engines into ~/.vyges/bin
vyges loom sta-si demo # run any engine as: vyges loom <engine> ...
Each engine is also a standalone vyges-<engine> binary on your PATH (e.g.
vyges-sta-si), which is what vyges loom <engine> dispatches to and what flow
authors integrate against directly.
Verify
vyges --version
vyges modules # shows which Vyges modules are installed (incl. the loom suite)
Supported platforms
- macOS (Apple Silicon)
- Linux (x86-64 and arm64)
- Windows (x86-64)
Output & logging
Vyges follows the Unix output contract, so its output composes cleanly with pipes, redirection, and other tools:
- stdout — data. Command results: tables, JSON, resolved paths, URLs. This is what you capture, pipe, or parse.
- stderr — diagnostics. Progress notes, hints, warnings, and errors. This is what you read while a command runs, or send to a log.
Because the two streams are separate, you control logging with the shell — there is
no --log-file flag, and you don’t need one.
Structured events (Loom engines). The Loom sign-off engines additionally emit machine-readable structured events on stderr (
vyges-events/1.0JSONL) — the causal trail the MCP layer andvyges modelconsume. Filter them withVYGES_LOGand pick text vs JSONL withVYGES_LOG_FORMAT; see that page.
Redirecting output
vyges catalog search uart > results.txt # data only → file
vyges catalog search uart 2> run.log # diagnostics only → file
vyges catalog search uart > out.txt 2>&1 # both → one file (data + diagnostics)
vyges catalog search uart 2>&1 | tee run.log # both to screen AND a log
vyges catalog search uart --json | jq '.[]' # data is clean JSON → pipe to a parser
Because data and diagnostics are separated, ... > results.txt gives you a file with
only the results — no progress chatter mixed in — while 2> run.log keeps a clean
log of what happened. This is the recommended way to “save a log”: let the shell do it.
Tip: for machine consumption, prefer
--json(supported by most commands) over scraping human output. Combined with2>/dev/nullyou get a pure JSON stream.
Verbosity
How much goes to stderr is controlled by a level. It never affects stdout — your data is never suppressed.
| Flag | Level | Shows on stderr |
|---|---|---|
-q -q -q | off | nothing (exit code still signals errors) |
-q -q | error | errors only |
-q | warn | errors + warnings |
| (default) | info | errors + warnings + info/hints |
-v | debug | + debug detail |
-v -v | trace | + trace detail |
-v and -q are repeatable and combine (the net of the two steps from info).
The VYGES_LOG environment variable
Set the level by name or number (0–5) without flags:
export VYGES_LOG=debug # or: off | error | warn | info | trace | 0..5
vyges pdk-store resolve sky130A lib --corner tt_025C_1v80
VYGES_LOG is inherited by child processes, so when vyges <tool> … dispatches to
a vyges-<tool> binary, the whole command tree runs at the same level — set it once.
Precedence (highest first): -v/-q flags → VYGES_LOG → default (info).
So a flag on an invocation overrides the environment for that process; the
environment configures everything else, including dispatched tools.
A flag binds to the process you give it to. vyges -v <tool> … makes vyges
verbose; the flag is consumed before dispatch, so the child tool is unaffected. To
make the child verbose, either set VYGES_LOG (it covers the whole tree) or pass
the flag after the tool name so it goes through to the child:
VYGES_LOG=debug vyges pdk-store list # whole tree verbose (env — simplest)
vyges -v modules # the `vyges` command itself, verbose
vyges pdk-store -v list # flag passes through → vyges-pdk-store verbose
AI IDE integration — vyges mcp
vyges mcp starts a local, no-auth MCP server that exposes your installed Loom engines
to an AI IDE (Claude Code, the VS Code Claude extension, or any MCP client). The agent calls the
engines as tools; the engines run on your machine, over stdio — no port, no auth, nothing
leaves your box (your own binaries, your own agent).
It is the execution companion to the CLI’s “deterministic core, agent tail” philosophy
(vyges agents): instead of the agent shelling vyges <tool>, the tools are MCP tools.
Do you need an LLM? Two ways if you do
The engines and tools are plain, deterministic CLIs — run them directly (vyges drc run …) or
script them, no LLM required. That is one of three ways to reach the same Loom engines —
manual, your own model via an AI IDE, or a model vyges drives for you:
1. MANUAL 2. AI IDE (Mode 1) 3. vyges model run (Mode 2)
no LLM · scriptable bring your own model registered model, headless
│ │ │
│ Claude Code / Cursor vyges driver
│ (any MCP host) (openai-compat | anthropic)
│ │ │
│ └────────────┬───────────────┘
│ ▼
│ ┌──────────────────────────────┐
│ │ vyges mcp · tool server │
│ │ (model-agnostic) │
│ └──────────────────────────────┘
│ │
▼ ▼
┌────────────────────────────────────────────────────────────┐
│ Loom engines — the deterministic core │
│ ground truth · the same engines every path drives, │
│ with or without an LLM on top · reproducible │
└────────────────────────────────────────────────────────────┘
The two AI paths go through the model-agnostic vyges mcp tool server; the manual path calls the
engines directly. Reach for an LLM only when you want reasoning over the tools («which engine,
why, and fix the violations»), not a fixed sequence — then there are two ways to connect one:
- Mode 1 — bring your own AI IDE (available today). Point Claude Code, Cursor, or any MCP
client at
vyges mcp. Your IDE’s model reasons and calls the tools — you bring the model, vyges brings the tools. This is the recommended interactive path, and the rest of this page covers it. - Mode 2 — register a model, vyges drives it (headless). Register a local or cloud model with
vyges model, thenvyges model run <name> "<task>"runs the reason → tool-call → observe loop over these tools itself, with no IDE — for headless / CI / air-gapped / autonomous flows. Because the model is a registered, swappable choice, point it at a local model so nothing leaves your machine. (v1 uses JSON tool-calling and passthrough tool args; native provider tool-calling and finer controls are refinements.)
Both modes drive the same vyges mcp tools below — the tool server is model-agnostic.
Quickstart — hook your AI IDE to your local Loom
# 1. Install the engines (once).
vyges install loom
# 2. Register with every AI IDE on your machine (user scope).
vyges mcp setup
vyges mcp setup detects the AI IDEs you have installed — Claude Code, Cursor, and
VS Code — and registers vyges mcp with each (merge-safe: it never disturbs your other MCP
servers, e.g. VyContext). Preview it with vyges mcp setup --dry-run; reverse it with
vyges mcp setup --uninstall.
First-run prompt: the very first time you run
vygesinteractively, it offers to do this for you (once). Decline and it won’t ask again; runvyges mcp setupyourself anytime. SetVYGES_NO_PROMPT=1to silence it.
Now open a project in your IDE — the installed engines appear as tools. Verify with:
claude mcp list # → vyges: … ✔ Connected
vyges mcp --list # the tools this server advertises
Just one project instead? vyges mcp install writes a project-scoped .mcp.json in the
current directory (equivalently: claude mcp add vyges -- vyges mcp).
What you get
-
One tool per installed engine (
drc,lvs,sta-si,gds-view, …). The tool set is discovered fromvyges modules— install more engines and they appear; nothing to configure. -
Calling a tool runs the real
vyges-<engine>and returns a structured result: the engine’s own--jsonoutput, wrapped in aloom-resultenvelope (status,engineering, a content-addressedinput_hash,provenance). Errors come back as a structured envelope too — a bad call never crashes the session. -
Two independent status axes.
statussays whether the process ran (ok|error);engineering.statussays what the evidence supports about your design (pass|fail|unknown|not_applicable). They are deliberately separate: a DRC run that exits cleanly having found 3 violations isstatus: "ok"withengineering.status: "fail"— a successful call reporting a failed check. An engine that crashes isunknown, neverfail, because a tooling defect is not a design defect; so is an engine that declares no assertion. Nothing is ever reported as passing on absent evidence.{ "status": "ok", "engineering": { "status": "fail", "assertion": "drc-clean", "summary": "3 rule violation(s) found" } } -
Typed arguments. Engines self-describe (
vyges-<engine> --describe), so their tools expose real per-parameter schemas —drctakesgds,deck,top, not an opaque string. Tools without a descriptor (and external tools likeyosys) fall back to anargsarray of the engine’s own CLI arguments;--jsonis added automatically either way. The descriptor format is documented in Tool descriptor —--describe, and the result shape in Result envelope —loom-result.
Read-only vs mutating tools — VYGES_MCP_PROFILE
Not every engine is equal: sign-off, verification, and query engines only read your design
(sta-si, drc, lvs, extract, power, em-ir, thermal, cdc, glitch, lec, gds-view),
while optimizers edit it (resize, vt-swap, buffer-insert, hold-fix, remap). vyges mcp
classifies each tool automatically — from what it produces — and lets you choose how much of the
surface an agent sees:
VYGES_MCP_PROFILE | Exposes | Use it for |
|---|---|---|
full (default) | every tool | unrestricted local use — unchanged behavior |
core | read-only engines only (sign-off / verify / query) | let an agent analyze and explain your design with no way to change it |
pro | read-only + mutating engines behind an approving transaction | agent-driven optimization with a human in the loop |
VYGES_MCP_PROFILE=core vyges mcp # read-only surface: the agent can run sign-off, never edit
vyges mcp --list shows each tool’s read/mutate classification and whether it’s exposed under the
active profile. (External and passthrough tools — which can write — are treated as mutating, so a
core surface is strictly the engines proven read-only.)
Approving a change — transactions (pro)
Under pro, a mutating engine runs only inside an open transaction — opening one is your explicit
go-ahead to let the agent change the design this session:
txn.begin # authorize mutations for this session
… agent runs resize / hold-fix / … — each change is staged, not adopted …
txn.status # review what's staged
txn.commit # accept the staged changes —or— txn.rollback # discard them
audit.events # the full trail of what ran this session
Because the optimizers are non-destructive (they write a new netlist and never touch your
input), txn.rollback simply discards the candidates — there is nothing to restore.
Keep-best timing closure — flow.close_timing
flow.close_timing runs the safe loop for you: it signs off the design, then tries each optimizer
in turn, re-signs-off the result, and keeps a candidate only if timing did not regress —
threading the adopted netlist into the next step. The agent proposes; the deterministic engine
decides. You give it a sign-off job (and optionally the steps to try); it returns baseline vs
final and which steps were kept:
flow.close_timing { "job": "counter.sta", "steps": ["resize", "hold-fix"] }
→ { baseline: {wns_ns …}, final: {wns_ns …}, improved_ns, kept_any, steps:[…] }
It writes candidate netlists, so it runs under the same gate as the optimizers (an open
transaction under pro).
Commands
vyges mcp start the stdio server (an MCP client spawns this)
vyges mcp setup [--dry-run] [--uninstall]
register with every detected AI IDE (user scope)
vyges mcp install [dir] register in <dir>/.mcp.json (one project)
vyges mcp uninstall [dir] remove the project registration
vyges mcp --list list the tools this server would advertise
Both setup and install are safe to run alongside VyContext and any other MCP servers —
they read-modify-write each config, preserving existing entries. (Antigravity is detected but
not yet wired — its MCP config path is being confirmed.)
Your tools, your workflow — open or commercial
vyges mcp is tool-agnostic: beyond the Loom engines, any resolvable non-Vyges EDA tool is
advertised too, so an agent drives your whole flow, not just Loom.
- Open source — yosys, verilator, klayout, openroad, magic, netgen.
- Commercial (COTS) — Synopsys (primetime, starrc, fusioncompiler), Cadence (genus, innovus, tempus, quantus), Siemens (calibre) — each advertised when it’s resolvable on your host.
Arguments pass through verbatim and output comes back as text (structured per-tool schemas are a
later refinement). Point each tool at its install — including a licensed commercial tool on an
NFS-mounted toolshed — in tools.json (next section), with license variables via env; paths,
versions, and license settings depend on your site’s install layout and deployment architecture and
are tuned to match. The agent then drives one interface across Loom, open-source, and commercial
tools — your existing methodology wrapped, not replaced.
Pinning versions (and containers)
vyges mcp setup already drops a starter ~/.vyges/tools.json (carrying the $schema line) in
place, so your editor and AI assistant can autocomplete pins immediately — nothing extra to run.
(vyges mcp tools --init writes the same starter on demand.)
Hosts often carry several versions of a tool. Pin exactly which one an adapter uses in that
tools.json — user-scope ~/.vyges/tools.json or project-scope .vyges/tools.json (project
wins), with an env override VYGES_TOOL_<NAME> on top and PATH as the fallback:
{
"env": { "SNPSLMD_LICENSE_FILE": "27020@lic.corp" }, // license servers (forwarded to every tool)
"tools": {
"yosys": { "path": "/opt/yosys-0.40/bin/yosys" },
"primetime": { "path": "/eda/synopsys/pt/T-2022.03/bin/pt_shell" }, // licensed tool on an NFS toolshed
"klayout": {
"container": {
"runtime": "podman",
"image": "klayout:0.28.17",
"entrypoint": "klayout",
"mounts": ["/pdk:/pdk:ro", "/data:/data"]
}
}
}
}
A container-backed tool runs via podman/docker run with your working directory
auto-mounted 1:1 (so paths in the args resolve inside), and the image tag is the pinned
version:
mounts— extra-v host:container[:ro]volumes. This is the common enterprise case: mount your PDK, a license directory, or a shared data volume into the container; append:rofor read-only.entrypoint— the command inside the container (default: the tool name). Set it to""to use the image’s ownENTRYPOINT, or to a full in-container path.
Check how everything resolves on a host — engines and external tools, with the pinned path/image, version, and which source each came from — with:
vyges mcp tools
Safe to hand-edit. A malformed tools.json is never fatal — it’s validated and any problems
(bad JSON, a container with no image, an unknown key, path and container together) are
reported by vyges mcp tools and at server startup, with resolution simply falling back to
PATH. For editor autocomplete + as-you-type checking, add a $schema line pointing at the
shipped schema:
{ "$schema": "https://vyges.com/schema/v1/tools.schema.json", "tools": { … } }
The resolved binary/image and its version are recorded in every result and folded into the content hash, so swapping a version can never silently reuse a stale result.
Agentic feedback — loom.feedback
Beyond the per-engine tools, the server exposes loom.feedback — the agent’s “eyes” for a
layout iteration: one bundle of a render (gds-view), categorized DRC verdicts, and a
score (violation counts, and correlation to a golden if you pass one). It’s also a CLI:
vyges mcp feedback design.gds --rules sky130.drc [--top TOP] [--golden 0]
An agent calls loom.feedback, reads { render, verdicts, score }, decides the next edit, and
re-runs — the closure loop, on your machine.
Trust & tiers
This is the free, local, no-auth tier: it exposes your own installed binaries to your own
local agent — the same trust model as any local dev MCP server. Even here you stay in control of
what an agent can touch: the read-only core profile and per-session transactions above are yours by
default. Governed, distributed execution (RBAC, audit, running tools across a fleet) is a separate
enterprise tier (Vyges Mill), not this server.
See the vyges mcp command reference for the generated help.
vyges mcp
Generated from vyges-mcp --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-mcp — local stdio MCP server exposing the installed Vyges Loom engines
usage:
vyges mcp start the stdio MCP server (an MCP client spawns this)
vyges mcp tools show how each engine + external tool resolves on this host
vyges mcp tools --init write a starter ~/.vyges/tools.json (with $schema) to pin from
vyges mcp tools --upgrade migrate an older tools.json to the current schema (backs up .bak)
vyges mcp feedback <gds> --rules <deck> [--top C] [--golden G] [-o SVG]
agentic feedback bundle: render + DRC verdicts + score
vyges mcp emap <netlist> --top T --lib L.lib [--lib …] --lef X.lef [--lef …]
[--sdc S] [-o out.v] [--no-multioutput] [--scene fast]
multi-output techmap (OpenROAD resynth_emap): before/after/delta
vyges mcp setup [--dry-run] [--uninstall]
detect installed AI IDEs (Claude Code / Cursor / VS Code)
and register `vyges mcp` with each (user scope)
vyges mcp install [dir] register `vyges mcp` in <dir>/.mcp.json (project scope)
vyges mcp uninstall [dir] remove it from <dir>/.mcp.json
vyges mcp --list print the tools this server would advertise, then exit
vyges mcp --version print the version
vyges mcp --help show this help
No port, no auth: the server talks JSON-RPC over stdin/stdout and exposes your
own installed `vyges-<engine>` binaries to your own local agent. Install engines
with `vyges install loom`, then `vyges mcp setup` (all your AI IDEs) or
`vyges mcp install` (just this project).
vyges model
A model/provider registry for the Vyges agentic layer. It names AI models and resolves their
connection details (backend · endpoint · model id · tool-calling capability · local/cloud) so the
model is a registered, swappable choice — the same thin-descriptor + resolve pattern as
vyges pdk-store, applied to models.
This is the configuration used by Mode 2 —
when vyges itself drives the tools with a model you choose. (In Mode 1, your AI IDE owns the
model and no registration is needed.) Register a model, then drive the tools with
vyges model run.
Local models come first
Vyges is model-agnostic, and local models are the primary path — the design data your agent
reasons over never leaves your machine. Serve an open model on an OpenAI-compatible endpoint
(ollama, llama.cpp-server, vLLM, TGI — each exposes /v1) and register it with --local:
vyges model add semikong --backend openai-compat \
--endpoint http://127.0.0.1:11434/v1 --model semikong-8b-q4 --tool-calling json --local
vyges model check semikong # is the endpoint reachable?
vyges model resolve semikong endpoint # http://127.0.0.1:11434/v1
Cloud models — API keys and URLs
Cloud models (Anthropic, OpenAI, …) are fully supported and are often the easiest way to start when your organization already has a subscription or corporate agreement. Two things to configure: a key and, optionally, a base URL.
Keys are a reference, never the secret
--api-key stores an environment-variable reference (e.g. $ANTHROPIC_API_KEY) — not the key
itself. The driver expands it from the environment at call time, so no secret ever lands in
model.json (safe to commit ./.vyges/model.json to a repo). Export the real key in your shell
or CI secret store:
export ANTHROPIC_API_KEY=sk-ant-…
export OPENAI_API_KEY=sk-…
Per provider
Anthropic (Claude) — the default endpoint is api.anthropic.com, so omit --endpoint:
vyges model add claude --backend anthropic --model claude-sonnet-5 \
--api-key '$ANTHROPIC_API_KEY' --tool-calling native --cloud
Route Claude through a corporate gateway / Bedrock- or Vertex-style proxy that speaks the
Anthropic Messages API by pointing --endpoint at its base URL (the driver appends /v1/messages;
a full …/messages URL is used as-is):
vyges model add claude-gw --backend anthropic --endpoint https://claude-gw.corp.com \
--model claude-sonnet-5 --api-key '$CLAUDE_GW_KEY' --tool-calling native --cloud
OpenAI:
vyges model add gpt --backend openai-compat --endpoint https://api.openai.com/v1 \
--model gpt-4o --api-key '$OPENAI_API_KEY' --tool-calling native --cloud
Grok (xAI) — OpenAI-compatible, just a different base URL:
vyges model add grok --backend openai-compat --endpoint https://api.x.ai/v1 \
--model grok-2 --api-key '$XAI_API_KEY' --tool-calling native --cloud
Azure OpenAI / a corporate OpenAI gateway — point --endpoint at your deployment base (the
driver appends /chat/completions):
vyges model add azure --backend openai-compat \
--endpoint https://my-resource.openai.azure.com/openai/deployments/gpt4o \
--model gpt-4o --api-key '$AZURE_OPENAI_KEY' --tool-calling native --cloud
Per-invocation / CI override
Override any model inline — without editing model.json — with a VYGES_MODEL_<NAME> env var
holding a JSON object (handy in CI, where the endpoint/key vary per environment):
export VYGES_MODEL_GROK='{"backend":"openai-compat","endpoint":"https://api.x.ai/v1","model":"grok-2","api_key":"$XAI_API_KEY","local":false}'
Drive the tools (Mode 2)
Once a model is registered, run a task — vyges presents the installed vyges mcp tools to the
model and runs the reason → tool-call → observe loop until the model signals done:
vyges model run semikong "check DRC on block1.gds with the sky130 deck and report the count"
Point it at a local model and the design data your agent reasons over never leaves your machine. (v1 uses JSON tool-calling and passthrough tool arguments; native provider tool-calling and finer controls are refinements.)
Commands
vyges model list list registered models
vyges model add <name> … register into ~/.vyges/model.json
vyges model resolve <name> <key> print one field (endpoint | model | tool_calling | local | …)
vyges model check <name> report reachability of the model endpoint
vyges model run <name> "<task>" drive the vyges mcp tools with the model (Mode 2)
model.json
Registrations live in a models map. Resolution order (first hit wins), mirroring tools.json:
- env
VYGES_MODEL_<NAME>— a JSON object (per-invocation / CI override) - project
./.vyges/model.json— a repo pins its model - user
~/.vyges/model.json— the host default
Two backends cover every provider: openai-compat (OpenAI, Grok/xAI, and OSS servers — ollama,
llama.cpp-server, vLLM, TGI) and anthropic (Claude native).
{
"$schema": "https://vyges.com/schema/v1/model.schema.json",
"models": {
"semikong": { "backend": "openai-compat", "endpoint": "http://127.0.0.1:11434/v1",
"model": "semikong-8b-q4", "tool_calling": "json", "local": true },
"claude": { "backend": "anthropic", "model": "claude-sonnet-5", "api_key": "$ANTHROPIC_API_KEY",
"tool_calling": "native", "local": false, "egress": "metadata-only" }
}
}
Local vs cloud — and data egress
Mark each model --local or --cloud so it is explicit which models can see your design data.
Local is the recommended default: the data your agent reasons over never leaves the machine —
the same local-first trust model as the rest of the CLI.
For a cloud model the data leaves your boundary, so govern which models are allowed. Vyges is deliberately not a data-loss / egress firewall: local models keep data on the machine by construction, and for cloud models you enforce with your organization’s existing egress controls (proxy / CASB / DLP). Vyges records which model each call used; it does not claim to prevent leakage.
vyges
Generated from vyges --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
Vyges — one CLI for the Vyges hardware-IP toolchain.
`vyges modules` lists the promoted tools; `vyges agents` prints the agent guide. An
unknown subcommand dispatches to an external `vyges-<name>` binary on PATH (e.g.
`vyges pdk-store …` runs vyges-pdk-store). Report bugs/features centrally with
`vyges --bug-report` / `--feature-request`, or support Vyges with `vyges --sponsor`.
Usage: vyges [OPTIONS] [COMMAND]
Commands:
modules List the promoted Vyges modules and whether each is installed
agents Print the operating guide for AI IDE agents
install Install an on-demand engine: fetch the prebuilt `vyges-<tool>` from its public `vyges-tools/<tool>` GitHub release into `~/.vyges/bin`. `vyges install loom` installs the whole Vyges Loom suite at once
cache Inspect or clear the Liberty parse cache (`~/.vyges/cache/liberty`) — the shared parse-once store the timing/power engines use
help Print this message or the help of the given subcommand(s)
Options:
-v, --verbose...
Increase diagnostic verbosity (stderr): -v debug, -vv trace. Repeatable
-q, --quiet...
Reduce diagnostics (stderr): -q warnings-only, -qq errors-only, -qqq silent. Repeatable. Overrides VYGES_LOG. (Data on stdout is never suppressed.)
--bug-report
File a bug report (central — vyges/community issues)
--feature-request
File a feature request (central — vyges/community issues)
--sponsor
Sponsor Vyges (github.com/sponsors/vyges-ip)
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
vyges pdk-store
Generated from vyges-pdk-store --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-pdk-store — consistent PDK presentation + resolution
usage:
vyges-pdk-store list list registered PDKs
vyges-pdk-store show <name|file.vyges-pdk.json> show a PDK + its collateral
vyges-pdk-store validate <file.vyges-pdk.json> schema-validate a descriptor
vyges-pdk-store add <name|file.vyges-pdk.json> [--force] register into the user store
vyges-pdk-store deregister <name> remove a registration (keeps data)
vyges-pdk-store use <name> [--local] set the selected (*) PDK (global, or ./.vyges)
vyges-pdk-store resolve <name|file> <key> [--corner C] [--library L]
print collateral path(s) for a flow
vyges-pdk-store verify <name|file> check collateral paths exist
vyges-pdk-store fetch <name|file> [--dry-run] materialize PDK data (git mirror / Ciel)
vyges-pdk-store refresh [--dry-run] refresh the catalog from vyges-tools/pdk-catalog
keys for resolve: tech_lef | lvs_device_rules | drc_deck | lvs_deck | primitives_spice |
models (per --corner) | lib (per --corner + --library) |
spice | gds | lef | verilog (per --library) | <any collateral key>
note: lvs_device_rules is vyges-lvs's device-recognition deck (GDS->SPICE layer/datatype
mapping). It was called extract_rules, which read as parasitic extraction; the old
name still resolves but is deprecated. RC parasitics are NOT collateral --
vyges-extract derives them from the tech LEF (+ an OpenRCX captable when the LEF is
geometry-only) and caches them beside that LEF.
flags: --corner <name> · --library <name> · --force · --dry-run · --local · -h/--help · -V/--version
-v/--verbose · -q/--quiet (stderr diagnostics; or set VYGES_LOG=off|error|warn|info|debug|trace)
vyges catalog
Generated from vyges-catalog --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-catalog — search the Vyges IP catalog
usage:
vyges-catalog search <query> [--category C] [--keyword K] [--json]
find IPs by name / category / keyword
vyges-catalog show <name> [--json] show one IP (incl. license)
vyges-catalog license <name> print one IP's license (SPDX)
vyges-catalog categories [--json] list categories (with counts)
vyges-catalog sources [--json] list configured sources + cache status
vyges-catalog refresh [--source N] [--dry-run]
fetch source indexes (like `apt update`)
vyges-catalog fetch <ip[@version]> [--force] [--dry-run]
materialize an open IP into ~/.vyges/catalog/ip/<name>/<version>
vyges-catalog fetch --private <url|path>[@version]
materialize a private/NDA IP into ~/.vyges/catalog/private_ip/ (segregated)
from a repo URL/org-repo (clone) or a local directory (import);
version optional — derived from vyges-metadata.json if omitted
vyges-catalog cached [--json] list locally installed (cached) IPs + versions
(aliases: installed, ls)
vyges-catalog path <ip[@version]> print a cached IP's path (for flows)
vyges-catalog verify <ip[@version]> check a cached IP is intact
vyges-catalog rm <ip[@version]> remove cached version(s) of an IP
vyges-catalog prune [--dry-run] remove the whole local IP cache
Search-first by design (no bulk dump). Sources: a built-in `oss` catalog plus any
enterprise catalogs in ~/.vyges/catalog/sources.conf (line: `name url [TOKEN_ENV]`).
flags: --category <c> · --keyword <k> · --source <n> · --private · --force · --json · --dry-run · -h · -V
-v/--verbose · -q/--quiet (stderr diagnostics; or set VYGES_LOG=off|error|warn|info|debug|trace)
vyges metadata
Generated from vyges-metadata --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-metadata — work with an IP's vyges-metadata.json
usage:
vyges-metadata reconcile <path> [options] check metadata against its RTL
vyges-metadata update <path> [options] reconcile + WRITE: fill gaps AND
resolve drift (destructive)
vyges-metadata validate <path> [options] check metadata against the schema
vyges-metadata create <path> [options] generate a metadata skeleton from RTL
vyges-metadata schema [field] [--json] describe the schema's required/optional
fields (introspection; no file needed)
create options:
--rtl <dir> RTL source directory (default: <path>/rtl)
--name <name> IP name (default: the directory name)
--metadata <file> output filename (default: vyges-metadata.json)
--force overwrite an existing metadata file
validate options:
--metadata <file> metadata filename to read (default: vyges-metadata.json)
--json / --quiet machine-readable / only invalid IPs
--fail-on-error exit non-zero if any IP fails the schema (CI gate)
reconcile options:
--rtl <dir> RTL source directory (default: <path>/rtl)
--rtl-test <dir> testbench directory (reserved — used by `create`)
--metadata <file> metadata filename to read in each IP dir
(default: vyges-metadata.json; point at e.g.
my_test_metadata.json to compare an alternative for drift)
--json machine-readable output
--quiet, -q only report IPs that have issues
--fail-on-drift exit non-zero if any metadata/RTL drift is found (CI gate)
--write merge the proposed additions (clock/reset/top_module) into
the metadata file; refreshes 'updated'. Asks before writing.
Refuses an IP if the change introduces NEW schema errors.
--yes, -y with --write, skip the per-IP confirmation prompt
--no-schema-gate with --write, skip the schema delta check
<path> is a single IP directory (with the metadata file) or a directory of
cached IPs (each subdir an IP). Reports per dimension: ok / GAP (RTL has it,
metadata omits it) / DRIFT (metadata claims it, the RTL doesn't).
Vyges Loom — the open EDA sign-off & optimization suite
The Loom suite, under
vyges. Install once —vyges install loom— then run any engine asvyges loom <engine>(e.g.vyges loom sta-si run top.sta). Each engine is also a standalonevyges-<engine>binary on your PATH, which is what the dispatch calls and the integration contract flow authors target directly (see integrating into a flow).
Commercial-grade engines — sign-off that analyzes and optimizers that
act on the result — each driven by a declarative job file that produces a
standard artifact. They share one cross-engine data spine (vyges-loom) — the
output of one is the input of the next, with no glue scripts:
.ext ─► vyges loom extract ─► .spef ──┐
.char ─► vyges loom char ─► .lib ──┼─► vyges loom sta-si ─► WNS / TNS ─► resize · vt-swap · buffer-insert ─► fixed netlist
└─► vyges loom power ─► activity ─┬─► vyges loom em-ir ─► IR-drop + EM
└─► vyges loom thermal ─► temp / hotspot
.gds + rules ─► vyges loom lvs ─► MATCH / MISMATCH
| Engine | Command | Job file | Output |
|---|---|---|---|
| char | vyges loom char | .char / .charlib | Liberty .lib |
| extract | vyges loom extract | .ext | SPEF |
| power | vyges loom power | .pwr | power report + activity map |
| sta-si | vyges loom sta-si | .sta | WNS / TNS / worst path |
| em-ir | vyges loom em-ir | .emir | IR-drop map + EM check |
| thermal | vyges loom thermal | .thermal | temperature field + hotspot |
| lvs | vyges loom lvs | .lvs | MATCH / MISMATCH + diagnostics |
Optimizers — they read the timer’s verdict and edit the netlist to fix it:
| Engine | Command | Job file | Output |
|---|---|---|---|
| resize | vyges loom resize | .resize | resized netlist (drive sizing) |
| vt-swap | vyges loom vt-swap | .vtswap | resized netlist (Vt / leakage) |
| buffer-insert | vyges loom buffer-insert | .bufins | buffered netlist (transition fix) |
Verification + utilities — prove correctness, or view the layout:
| Engine | Command | Input | Output |
|---|---|---|---|
| drc | vyges loom drc | GDS + .drc deck | geometry violations |
| cdc | vyges loom cdc | netlist + lib + SDC | clock-domain crossings |
| glitch | vyges loom glitch | netlist + Liberty | reconvergent-fanout hazards |
| lec | vyges loom lec | two netlists + lib | EQUIVALENT / NOT + counter-ex. |
| gds-view | vyges loom gds-view | GDS (+ marks) | layered SVG with overlay |
Domain coverage. The suite is a digital sign-off / optimization flow; on top of that, lvs, layout, em-ir, thermal and extract additionally cover analog / mixed-signal physical & integrity verification — LVS, geometry, IR / EM, thermal, and RC. Analog functional / timing sign-off is out of scope.
Open core
Every engine is Apache-2.0 and runnable today. The per-foundry calibration plugins (NDA) stay private — the engine is open, the fab-specific accuracy is gated.
One declarative job in, one standard artifact out
No Tcl, no glue scripts: describe the job, get a standard sign-off file. The timing and power engines exit non-zero on a violation, so they gate CI directly. See job-file formats.
vyges-char — standard-cell characterization
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom char. It’s also a standalonevyges-charbinary on your PATH (the integration contract for flow authors).
vyges-char generates a Liberty (.lib) timing & power library from SPICE
models, orchestrating the SPICE runs in parallel from one declarative job file.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom char demo # instant sample .lib (no sim)
vyges loom char run inv.char -o inv.lib # one cell → Liberty
vyges loom char library cells.charlib -o out/ # many cells, in parallel → merged .lib
vyges loom char check inv.char # validate the job
See the full CLI reference (generated from --help).
Where it sits
.char job in → .lib out. That .lib feeds vyges-sta-si, and
its per-switch energy feeds vyges-em-ir. See the data spine.
Domain coverage
vyges-char produces Liberty standard-cell timing & power models — NLDM / CCS tables,
timing arcs, slew × load delay surfaces — for a library of fixed-footprint logic cells. It is a
digital sign-off input and does not apply to analog / mixed-signal blocks, whose behavior
has no standard-cell or Liberty-arc analogue. For analog / MS physical & integrity verification,
see lvs (connectivity), layout (geometry), em-ir
(IR / EM), thermal, and extract (RC).
Source & releases
- Repo: https://github.com/vyges-tools/char
- Binaries: https://github.com/vyges-tools/char/releases
- Apache-2.0. Per-foundry calibration plugins are separate (NDA).
vyges-char — CLI reference
Generated from vyges-char --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-char — standard-cell timing characterization (SPICE -> Liberty)
usage:
vyges-char run JOB [-o OUT] [--json] [--jobs N]
[--sparse RxC [--verify K]] | [--auto [--target PCT]]
characterize one cell. --sparse: simulate a
coarse RxC grid, surrogate-fill the rest.
--auto: self-tuning — keep sampling the
biggest gap until CV error <= target, fill.
--jobs: parallelize the per-point sweep.
vyges-char library MANIFEST [-o DIR] characterize many cells (parallel) -> merged .lib
vyges-char dataset [JOB] [-o OUT] [--format csv|jsonl] [--clean]
flatten characterization to a tidy
training table (no JOB = offline demo)
vyges-char surrogate [JOB] [--degree D] [--metric M] [--log] [--json]
fit a CPU surrogate on a grid subset,
report held-out error (no JOB = demo)
vyges-char check JOB
vyges-char demo [-o OUT] [--json]
flags:
-o FILE write output to FILE (default: stdout)
--json characterization summary as JSON instead of Liberty
--format FMT dataset format: csv (default) or jsonl
--clean dataset: drop flagged (non-physical, e.g. negative-delay) rows
--degree D surrogate polynomial degree per axis (default 2)
--metric M surrogate: restrict to one metric (e.g. cell_rise)
--log surrogate: fit in log-log space (NLDM grids are log-spaced)
--sparse RxC run: simulate only a coarse RxC grid, surrogate-fill the dense .lib
--verify K run --sparse: re-simulate K un-fitted points, report the real error
--jobs N run: parallelize the per-point ngspice sweep across N threads (N=auto: all cores)
--auto run: self-tuning active sampling to a target accuracy, then surrogate-fill
--target PCT run --auto: stop when LOO-CV error <= PCT% of peak (default 2.0)
--max-points N run --auto: cap simulated points (default: the full grid)
--seed RxC run --auto: initial seed grid (default 3x3)
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-extract — parasitic extraction
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom extract. It’s also a standalonevyges-extractbinary on your PATH (the integration contract for flow authors).
vyges-extract reads a routed layout and the PDK’s parasitic rules and produces
SPEF — the resistance and capacitance of every net — so timing and power
analysis reason about the real interconnect, not an idealized one.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom extract demo # instant sample SPEF (no setup)
vyges loom extract run design.ext -o design.spef # extract RC → SPEF
vyges loom extract run design.ext --json # per-net R/C summary
vyges loom extract check design.ext # validate the job
See the full CLI reference (generated from --help).
Where it sits
.ext job in → .spef out, read directly by vyges-sta-si.
Extraction accuracy is governed by the PDK’s parasitic rules — the engine is
open, the calibration is foundry-specific. See the data spine.
Digital and analog / mixed-signal
The RC math is geometry × rules only — area / fringe capacitance and sheet / via resistance
off the routed shapes, with no standard-cell or clocked-netlist assumption. So an analog /
mixed-signal routed layout extracts exactly as a digital one does. Supplied as DEF it extracts
today (the new examples/bias_gen/ is an analog bias-generator block); for GDS-only analog a new
connectivity-tracing adapter (src/gds.rs) builds the DefNet graph straight from geometry,
sitting above the unchanged RC core.
vyges loom extract run examples/bias_gen/bias_gen.ext -o bias_gen.spef # analog bias-gen layout → SPEF
Honest bounds, the same for analog and digital: shapes are treated as axis-aligned rectangles, a via is a layer overlap, and pins lump into the net’s SPEF node. Scope here is physical parasitic extraction; analog functional / timing sign-off is out of scope (that leans on external SPICE / behavioral tools).
Source & releases
- Repo: https://github.com/vyges-tools/extract
- Binaries: https://github.com/vyges-tools/extract/releases
- Apache-2.0. Per-foundry calibration plugins are separate (NDA).
vyges-extract — CLI reference
Generated from vyges-extract --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-extract — foundry-correlated RC parasitic extraction (DEF -> SPEF)
usage:
vyges-extract run JOB [-o OUT] [--json] [--pdk NAME | --tech-lef PATH] [--refresh]
[--captable PATH | --allow-incomplete-rc]
[--cell-lef CL --lib LIB] # std-cell *CONN hookup
vyges-extract gen-rc (--pdk NAME | --tech-lef PATH) [--refresh]
vyges-extract check JOB
vyges-extract demo [-o OUT] [--json]
vyges-extract klayout2spef --gds F --layermap M [--top CELL] [-o OUT] [--geom-out G]
[--def D --cell-lef CL --lib LIB]
[--runner podman [--image REF] [--mount DIR] | --python CMD]
[--routing-only] [--from-dump F] [--self-test]
klayout2spef drives a headless KLayout (LayoutToNetlist) over a GDS to write SPEF +
an EM geometry sidecar (per-segment layer/width/length) for current-density sign-off.
--runner podman wraps the driver in the vyges-klayout container; --self-test and
--from-dump run the parse→SPEF pipeline offline (no KLayout).
RC rules come from a job's `rules:`, or are DERIVED from the PDK tech LEF via
--pdk / --tech-lef (the metal stack is discovered, not hand-listed) and cached
as vyges-additions/<pdk>/vyges-extract-rc.rules (regenerate with --refresh). When
a tech LEF is geometry-only (no R/C), an OpenRCX captable supplies the numbers;
`run` refuses zero-R/C rules rather than report parasitics that are all zero.
flags:
--pdk NAME derive RC rules from the PDK tech LEF (resolved via pdk-store)
--tech-lef PATH derive RC rules from this tech LEF directly
--captable PATH OpenRCX rules file for R/C the LEF lacks (else pdk-store captable)
--refresh re-derive the cached RC rules
--allow-incomplete-rc extract even when a layer has no R/C (understates parasitics)
-o FILE write output to FILE (default: stdout)
--json per-net parasitics summary as JSON instead of SPEF
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
-j, --threads N parallel worker threads (default: all cores; 1 = serial)
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-power — power analysis
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom power. It’s also a standalonevyges-powerbinary on your PATH (the integration contract for flow authors).
vyges-power computes a design’s power — leakage, internal, and
switching — from a gate-level netlist and the Liberty models, using either a
measured activity file (VCD) or a vectorless probabilistic toggle factor. It also
emits the per-instance activity / current map that vyges-em-ir
consumes, so IR-drop is solved from real per-instance current — closing the
char → power → em-ir loop.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom power demo # instant: built-in design → power report
vyges loom power run block.pwr # leakage + internal + switching report
vyges loom power run block.pwr --fail-on-budget # exit 3 over the job's power budget (CI gate)
vyges loom power check block.pwr # validate the job
See the full CLI reference (generated from --help).
Where it sits
Netlist + .lib + activity (VCD or vectorless) → a power report, plus the
activity map em-ir reads. It can also read extracted wire caps (.spef) from
vyges-extract for switching power. Designed to gate CI: over-budget
returns a distinct non-zero exit code. See the data spine.
Domain coverage
vyges-power sums per-cell Liberty leakage and internal energy weighted by toggle activity
over a gate-level netlist — it is digital sign-off. It does not apply to analog /
mixed-signal blocks, whose power has no standard-cell or Liberty analogue (an analog block’s
operating-point current is an input to em-ir, not something this engine computes).
For analog / MS physical & integrity verification, see lvs (connectivity),
layout (geometry), em-ir (IR / EM), thermal, and
extract (RC).
Source & releases
- Repo: https://github.com/vyges-tools/power
- Binaries: https://github.com/vyges-tools/power/releases
- Apache-2.0.
vyges-power — CLI reference
Generated from vyges-power --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-power — gate-level power analysis (leakage + dynamic) with a CI gate
usage:
vyges-power run JOB [-o OUT] [--json] [--fail-on-budget]
vyges-power check JOB
vyges-power demo [-o OUT] [--json]
A JOB is a small declarative `.pwr` file (netlist + lib(s) + clock + activity).
With `vcd:` or `saif:` it uses measured per-net toggle rates; otherwise a
vectorless `activity:` factor × clock. With `emit_activity:` it writes the
per-instance map that vyges-em-ir consumes (closing char -> power -> em-ir).
flags:
-o FILE write the report to FILE (default: stdout)
--json machine-readable JSON instead of the text report
--fail-on-budget exit 3 if total power exceeds the job's power_budget_mw
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-sta-si — timing with signal integrity
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom sta-si. It’s also a standalonevyges-sta-sibinary on your PATH (the integration contract for flow authors).
vyges-sta-si checks whether a design meets timing — reporting worst negative
slack (WNS), total negative slack (TNS), and the critical path — while
accounting for signal-integrity coupling between nets. It reads the .lib
from vyges-char and the .spef from vyges-extract.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom sta-si demo # instant: built-in design → WNS/TNS
vyges loom sta-si run top.sta -o top.rpt # analyze → timing report
vyges loom sta-si run top.sta --fail-on-violation # exit 3 if WNS < 0 (CI gate)
vyges loom sta-si check top.sta # validate the job
See the full CLI reference (generated from --help).
Where it sits
.lib + .spef + design & constraints → WNS / TNS / worst path. Designed to gate
CI: a timing violation returns a distinct non-zero exit code. See
the data spine.
Domain coverage
vyges-sta-si builds a timing graph over Liberty cell arcs and propagates slews and
arrivals through a clocked gate-level netlist — it is digital sign-off. It does not
apply to analog / mixed-signal blocks, whose timing and behavior have no standard-cell or
Liberty-arc analogue. For analog / MS physical & integrity verification, see
lvs (connectivity), layout (geometry), em-ir (IR / EM),
thermal, and extract (RC).
Source & releases
- Repo: https://github.com/vyges-tools/sta-si
- Binaries: https://github.com/vyges-tools/sta-si/releases
- Apache-2.0. Per-foundry calibration plugins are separate (NDA).
vyges-sta-si — CLI reference
Generated from vyges-sta-si --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-sta-si — sign-off static timing analysis with signal integrity
usage:
vyges-sta-si run JOB [-o OUT] [--json] [--fail-on-violation] [--sdf FILE]
vyges-sta-si sdc-lint JOB [-o OUT] [--json] [--fail-on-violation]
vyges-sta-si check JOB
vyges-sta-si demo [-o OUT] [--json]
vyges-sta-si tcl SCRIPT [-o OUT] [--json] [--fail-on-violation] (experimental)
`sdc-lint` checks the SDC for completeness/consistency (unconstrained I/O, a clock with
no period, duplicate clocks, a clock on a port the design lacks) — independent of timing.
`tcl` runs an OpenSTA-style TCL *subset* (read_liberty/verilog/spef/sdc + inline SDC +
report_checks/report_wns/report_tns) through the Vyges engine — EXPERIMENTAL; not a TCL
interpreter and not a drop-in for LibreLane's corner.tcl. See docs/opensta-integration.md.
flags:
-o FILE write output to FILE (default: stdout)
--json machine-readable JSON instead of the text report
--fail-on-violation exit 3 if WNS < 0 (CI timing gate)
--pdk NAME resolve liberty from pdk-store (lib) when the job has none
--corner C PDK corner for --pdk (default: the PDK's default corner)
--liberty-nldm-only skip CCS (receiver_capacitance + output_current) at Liberty
load — faster/smaller for NLDM-only runs; forces the NLDM delay path
--emit-liberty-json FILE dump the merged Liberty IR (the shared model the timer +
vyges-power consume) as JSON for inspection / MCP, then run
--sdf FILE also write an SDF back-annotation file (IOPATH + setup/hold,
+ INTERCONNECT from SPEF) — feeds gate-level / back-annotated sim
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-em-ir — power integrity
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom em-ir. It’s also a standalonevyges-em-irbinary on your PATH (the integration contract for flow authors).
vyges-em-ir takes the design’s power-distribution network (PDN) and solves it —
reporting IR-drop (supply voltage lost across the grid) and checking
electromigration (EM) current limits against a budget. Its dynamic solve is
fed by the per-switch energy from vyges-char.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom em-ir demo # instant: built-in PDN → IR/EM
vyges loom em-ir run block.emir -o block.rpt # analyze → report
vyges loom em-ir run block.emir --fail-on-violation # exit 3 if over budget (CI gate)
vyges loom em-ir check block.emir # validate the job
See the full CLI reference (generated from --help).
Where it sits
design + PDN + IR/EM budget → IR-drop map + EM check. Turns power integrity from a late, manual sign-off step into a deterministic, CI-gated check. See the data spine.
Digital and analog / mixed-signal
The solve is G·V = I on a generic conductance matrix — there is no standard-cell or
Liberty assumption in the physics, only resistors, pads and per-node currents. Besides the DEF
path, the engine reads a generic .pdn resistor-network description (used when def: is
empty), so a hand-built analog / mixed-signal supply mesh solves exactly as a digital PDN
does. The examples/analog_bias/ job is a .pdn mesh with pads and analog op-point load
currents standing in for the per-instance digital activity.
vyges loom em-ir run examples/analog_bias/analog_bias.emir # analog bias mesh → IR-drop + EM
Power-integrity (IR / EM) applies to any grid; the only difference is where the node currents come from — digital switching activity or an analog operating point. Scope here is physical power-integrity; analog functional / timing sign-off is out of scope (that leans on external SPICE / behavioral tools).
Source & releases
- Repo: https://github.com/vyges-tools/em-ir
- Binaries: https://github.com/vyges-tools/em-ir/releases
- Apache-2.0. Per-foundry calibration plugins are separate (NDA).
vyges-em-ir — CLI reference
Generated from vyges-em-ir --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-em-ir — EM / IR-drop power-integrity sign-off (PDN -> report)
usage:
vyges-em-ir run JOB [-o OUT] [--json] [--fail-on-violation]
vyges-em-ir check JOB
vyges-em-ir demo [-o OUT] [--json]
vyges-em-ir em-density (--geom G | --spef S) --lef TECH.lef
[--current-map C | --net-current mA] [--fail-on-violation]
em-density is EM sign-off on *extracted SPEF*: it screens each metal segment's
current density (from the loom EM geom sidecar: layer + width) against the tech
LEF DCCURRENTDENSITY (and AC RMS/PEAK when the current map supplies them).
flags:
-o FILE write output to FILE (default: stdout)
--json machine-readable JSON instead of the text report
--fail-on-violation exit 3 if IR drop exceeds the limit or any EM segment fails
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-thermal — on-chip thermal
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom thermal. It’s also a standalonevyges-thermalbinary on your PATH (the integration contract for flow authors).
vyges-thermal lands the design’s power on the die as heat and solves the steady
state — reporting the peak temperature, the hotspot location, per-block
temperatures, and a PASS/FAIL against a temperature limit. It is the thermal dual of
vyges-em-ir: the same grid solve, temperature where em-ir has voltage. The
per-block power comes from vyges-power; with temperature-dependent leakage
it runs the electro-thermal loop to a fixed point (leakage heats the die, the hotter
die leaks more), so you get the real operating temperature — closing
char → power → em-ir → thermal → power.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom thermal demo # instant: built-in floorplan → temp + heat map
vyges loom thermal run block.thermal -o block.rpt # analyze → report
vyges loom thermal run block.thermal --fail-on-violation # exit 3 if over the limit (CI gate)
vyges loom thermal check block.thermal # validate the job
Job file
A .thermal job declares the die, the solver grid, the material parameters
(k_si, thickness_um, theta_ja), the ambient, and the temperature limit; a
floorplan: (.flp) places the blocks and their power (with an optional per-block
leakage portion for the coupling). Standard CLI: --json, --quiet, --verbose — and
like the rest of the suite it fails CI (exit 3) when the peak exceeds t_limit_c.
See the CLI reference for the full flag list, and
Job-file formats for the .thermal / .flp shapes.
Digital and analog / mixed-signal
The solve is G_th·ΔT = P on a tile grid built from a generic .flp block list — each block
is just name x y w h power, with no notion of where the power came from. It is fully
decoupled from the power source, so an analog / mixed-signal floorplan lands its heat and
solves exactly as a digital one does. The examples/pa/ job is an RF power-amplifier
floorplan whose concentrated dissipation produces a classic analog PA hotspot.
vyges loom thermal run examples/pa/pa.thermal # RF power-amplifier floorplan → temp + PA hotspot
Heat flow is heat flow; the block powers can come from digital activity or an analog op-point. Scope here is physical thermal analysis; analog functional / timing sign-off is out of scope (that leans on external SPICE / behavioral tools).
Correlation baseline: HotSpot (the canonical open on-chip thermal simulator) — there is no thermal tool inside OpenLane/OpenROAD, so vyges-thermal fills that gap.
vyges-thermal — CLI reference
Generated from vyges-thermal --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-thermal — steady-state on-chip thermal analysis (floorplan -> temperature)
usage:
vyges-thermal run JOB [-o OUT] [--json] [--fail-on-violation]
vyges-thermal check JOB
vyges-thermal demo [-o OUT] [--json]
A JOB is a small declarative `.thermal` file (die + grid + material params +
a `floorplan:` of blocks with placement and power). With per-block leakage and
`leak_alpha_per_c` it runs the electro-thermal coupling loop. The report gives
the peak temperature, the hotspot location, per-block temperatures, and a
PASS/FAIL against `t_limit_c`.
flags:
-o FILE write output to FILE (default: stdout)
--json machine-readable JSON instead of the text report
--fail-on-violation exit 3 if the peak temperature exceeds t_limit_c
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-lvs — layout-vs-schematic
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom lvs. It’s also a standalonevyges-lvsbinary on your PATH (the integration contract for flow authors).
vyges-lvs answers one question: does the layout implement the schematic? It
matches the two netlists as graphs — name-independent colour-refinement — and
returns a MATCH / MISMATCH verdict. When they diverge, it names the unmatched
devices and nets, where the open incumbent (Netgen) prints a terse “do not match.”
It can also extract the layout netlist straight from a GDS, so you don’t need a
separate extractor in the loop.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom lvs demo # instant: built-in netlist pair → verdict
vyges loom lvs run block.lvs # MATCH / MISMATCH + diagnostics
vyges loom lvs run block.lvs --fail-on-mismatch # exit 3 if not equivalent (CI gate)
vyges loom lvs extract block.gds --rules sky130.rules --top block # native GDS → SPICE
See the full CLI reference (generated from --help).
Where it sits
Layout netlist (or GDS + a layer .rules deck) + the schematic → MATCH / MISMATCH.
It’s the layout-correctness check at sign-off, beside the timing / power / PI
engines. Designed to gate CI: a mismatch returns a distinct non-zero exit code. See
the data spine.
Digital and analog / mixed-signal
The compare is device-kind-agnostic — it matches the netlist graph over the generic
SPICE primitives M/Q/R/C/L/D/X, with no standard-cell, Liberty, or clocked-netlist
assumption. So vyges loom lvs runs on analog and mixed-signal blocks exactly as it does
on digital ones (the one device-specific rule, MOSFET source/drain symmetry, is what analog
needs too).
vyges loom lvs run examples/inv_chain/match.lvs # digital: standard-cell inverter chain
vyges loom lvs run examples/bandgap/match.lvs # analog: bandgap (Q/R/C + PMOS mirror) → MATCH
vyges loom lvs run examples/bandgap/mismatch.lvs # analog: mis-wired sense resistor → MISMATCH
The bandgap example exercises bipolar transistors, resistors and a capacitor — device kinds
a digital LVS never sees. Scope here is physical connectivity (LVS); analog functional /
timing sign-off is out of scope (that leans on external SPICE / behavioral tools).
Correlated against the golden tools
On real sky130, vyges-lvs is checked against the reference open tools: native GDS
extraction is net-level identical to Magic on a standard cell (a full LVS MATCH,
hvt included); on a placed-and-routed block (the counter through OpenLane, 229 cell
instances) it reaches exact device parity with Magic — 842 transistors,
421 n / 421 p — in ~1.5 s; and on the verdict it agrees 3/3 with Netgen, while
naming the unmatched classes. Detail lives in the repo’s correlation/.
Source & releases
- Repo: https://github.com/vyges-tools/lvs
- Binaries: https://github.com/vyges-tools/lvs/releases
- Apache-2.0. Per-foundry device-recognition decks are separate (NDA).
vyges-lvs — CLI reference
Generated from vyges-lvs --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-lvs — layout-vs-schematic netlist comparison with clear divergence diagnostics
usage:
vyges-lvs run JOB [-o OUT] [--json] [--fail-on-mismatch]
vyges-lvs extract GDS (--rules RULES | --pdk NAME) [--top CELL] [-o out.spice]
vyges-lvs check JOB
vyges-lvs demo [-o OUT] [--json]
A JOB is a small declarative `.lvs` file: the layout side as a SPICE netlist
(`layout:`) OR a GDS to extract natively (`layout_gds:` + `rules:`/`pdk:`), plus
the `schematic:` and an optional `top:`. The compare is name-independent (graph
colour-refinement); a mismatch reports the unmatched device/net classes.
`extract` runs native device extraction (GDS/OASIS -> SPICE) on its own.
Extraction rules come from `--rules`/`rules:` directly, or are resolved from a
PDK by `--pdk`/`pdk:` NAME via the installed pdk-store (its `lvs_device_rules`).
flags:
--pdk NAME resolve extraction rules from pdk-store (vs --rules)
-o FILE write the report to FILE (default: stdout)
--json machine-readable JSON instead of the text report
--fail-on-mismatch exit 3 if the netlists are not equivalent (CI gate)
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-resize — gate sizing
Part of the Vyges Loom suite (optimizer). Install once with
vyges install loom, then runvyges loom resize. It’s also a standalonevyges-resizebinary on your PATH.
Where the sign-off engines say what’s wrong, the optimizers fix it. vyges-resize
picks a better drive strength for each cell — upsizing cells on the critical path to
close setup violations, downsizing cells with slack to recover area — then emits the
resized netlist. The logic never changes; only the cell variant does, and every candidate
is scored by the vyges-sta-si timer. Run it pre-place (ideal
interconnect) or as a post-place ECO by naming a spef: so sizing is scored against
the real wire RC.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom resize demo # instant: built-in example closes a violation
vyges loom resize run top.resize -o sized.v # size → resized netlist
vyges loom resize run top.resize --fail-on-violation # exit 3 if still violating (CI gate)
vyges loom resize check top.resize # validate the job
A .resize job is a superset of a .sta job plus group: (interchangeable cell families,
weakest → strongest), objective: (timing | area), effort:, and dont_touch:.
See the full CLI reference (generated from --help).
Where it sits
netlist + .lib + constraints (+ optional .spef) → resized netlist + before/after WNS/TNS.
It decides sizes, not locations — placement/routing stay the flow’s job. See
the data spine.
Domain coverage
vyges-resize swaps standard-cell drive strengths, scored by the digital
vyges-sta-si timer — it is digital optimization. It does not apply to
analog / mixed-signal blocks, which have no interchangeable standard-cell drive variants and no
Liberty-arc timing to score against. For analog / MS physical & integrity verification, see
lvs (connectivity), layout (geometry), em-ir
(IR / EM), thermal, and extract (RC).
Source & releases
- Repo: https://github.com/vyges-tools/resize
- Binaries: https://github.com/vyges-tools/resize/releases
- Apache-2.0. Per-foundry calibration plugins are separate (NDA).
vyges-resize — CLI reference
Generated from vyges-resize --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-resize — STA-driven gate sizing (drive-strength resize / Vt-swap to close timing)
usage:
vyges-resize run JOB [-o OUT] [--json] [--fail-on-violation] size a netlist -> resized netlist
vyges-resize check JOB validate the job
vyges-resize demo size a built-in example (no files)
flags:
-o FILE write the resized netlist to FILE (default: stdout)
--json emit the before/after report as JSON
--fail-on-violation exit 3 if the result still has negative setup slack (CI gate)
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-vt-swap — threshold-voltage swapping
Part of the Vyges Loom suite (optimizer). Install once with
vyges install loom, then runvyges loom vt-swap. It’s also a standalonevyges-vt-swapbinary on your PATH.
The sibling of vyges-resize: same timer-scored cell-swap loop, but it
trades threshold voltage (leakage/speed) instead of drive strength. A higher-Vt flavor
of a gate is slower but leaks far less; a lower-Vt flavor is faster but leakier. Two
objectives:
- leakage (default) — on a timing-met design, push every cell with positive slack to the highest-Vt (lowest-leakage) flavor that still meets timing. Free leakage recovery.
- timing — drop critical-path cells to a faster (lower-Vt) flavor to close setup.
It reports total cell leakage before and after (from the .lib’s cell_leakage_power)
alongside the timing it preserved.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom vt-swap demo # instant: built-in example recovers leakage
vyges loom vt-swap run top.vtswap -o swapped.v # swap → resized netlist
vyges loom vt-swap run top.vtswap --json # before/after timing + leakage
vyges loom vt-swap check top.vtswap # validate the job
A .vtswap job lists the iso-footprint Vt families fastest → slowest (low-Vt → high-Vt),
plus objective: (leakage | timing), effort:, and dont_touch:.
See the full CLI reference (generated from --help).
Where it sits
netlist + .lib + constraints (+ optional .spef) → resized netlist + before/after WNS and
leakage. Same footprint, so placement/routing are untouched. See the data spine.
Domain coverage
vyges-vt-swap trades standard-cell Vt flavors for leakage / setup, scored by the digital
vyges-sta-si timer — it is digital optimization. It does not apply to
analog / mixed-signal blocks, which have no iso-footprint Vt cell families and no Liberty-arc
timing to score against. For analog / MS physical & integrity verification, see
lvs (connectivity), layout (geometry), em-ir
(IR / EM), thermal, and extract (RC).
Source & releases
- Repo: https://github.com/vyges-tools/vt-swap
- Binaries: https://github.com/vyges-tools/vt-swap/releases
- Apache-2.0. Per-foundry calibration plugins are separate (NDA).
vyges-vt-swap — CLI reference
Generated from vyges-vt-swap --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-vt-swap — STA-driven threshold-voltage swapping (cut leakage / close setup, iso-footprint)
usage:
vyges-vt-swap run JOB [-o OUT] [--json] [--fail-on-violation] swap Vt -> resized netlist
vyges-vt-swap check JOB validate the job
vyges-vt-swap demo swap a built-in example (no files)
flags:
-o FILE write the resized netlist to FILE (default: stdout)
--json emit the before/after report as JSON
--fail-on-violation exit 3 if the result still has negative setup slack (CI gate)
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-buffer-insert — buffer insertion
Part of the Vyges Loom suite (optimizer). Install once with
vyges install loom, then runvyges loom buffer-insert. It’s also a standalonevyges-buffer-insertbinary on your PATH.
The third Loom optimizer. Where vyges-resize and
vyges-vt-swap swap a cell for one with the same footprint, this one
adds cells. When a net is so heavily loaded that its driver’s output transition exceeds
the limit, vyges-buffer-insert splits the net: a fresh buffer takes over a share of
the sinks so the original driver sees less load and switches faster. It keeps an insertion
only if the worst transition dropped without breaking setup, scored by the
vyges-sta-si timer.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom buffer-insert demo # instant: relieve a heavy net
vyges loom buffer-insert run top.bufins -o buffered.v # buffer → netlist
vyges loom buffer-insert run top.bufins --json # before/after slew + timing
vyges loom buffer-insert check top.bufins # validate the job
A .bufins job names the buffer: cell to insert, a max_slew: transition limit, a
min_fanout: threshold, effort:, and dont_touch:.
See the full CLI reference (generated from --help).
Where it sits
netlist + .lib + constraints (+ optional .spef) → buffered netlist + before/after worst
transition and WNS. A pre-place structural fixup — it decides where in the logical net
to split and hands placement of the new buffer back to the flow. See
the data spine.
Domain coverage
vyges-buffer-insert splits over-slew nets in a gate-level netlist with standard-cell
buffer cells, scored by the digital vyges-sta-si timer — it is digital
optimization. It does not apply to analog / mixed-signal blocks, which have no standard-cell
buffers or Liberty-arc transition limits to drive the fix. For analog / MS physical & integrity
verification, see lvs (connectivity), layout (geometry),
em-ir (IR / EM), thermal, and extract (RC).
Source & releases
- Repo: https://github.com/vyges-tools/buffer-insert
- Binaries: https://github.com/vyges-tools/buffer-insert/releases
- Apache-2.0. Per-foundry calibration plugins are separate (NDA).
vyges-buffer-insert — CLI reference
Generated from vyges-buffer-insert --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-buffer-insert — STA-driven buffer insertion (split over-transition / high-fanout nets)
usage:
vyges-buffer-insert run JOB [-o OUT] [--json] [--fail-on-violation] buffer -> resized netlist
vyges-buffer-insert check JOB validate the job
vyges-buffer-insert demo buffer a built-in example (no files)
flags:
-o FILE write the buffered netlist to FILE (default: stdout)
--json emit the before/after report as JSON
--fail-on-violation exit 3 if the result still has negative setup slack (CI gate)
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
--bug-report file a bug (central: vyges/community)
--feature-request request a feature (central)
--sponsor sponsor Vyges (github.com/sponsors/vyges-ip)
--star star this tool on GitHub ⭐
vyges-hold-fix — post-route hold-fix ECO
Part of the Vyges Loom suite (optimizer). Install once with
vyges install loom, then runvyges loom hold-fix. It’s also a standalonevyges-hold-fixbinary on your PATH.
The hold counterpart to the Loom optimizers. Where vyges-resize,
vyges-vt-swap, and vyges-buffer-insert all fix the
late / setup corner, hold violations are the opposite problem — data reaches a capture flop
too early on the min-delay path — and open place-and-route flows often leave a residue of
them after detailed routing. vyges-hold-fix adds delay: it inserts a delay cell in series
on the net feeding each hold-violating capture pin, lifting that pin’s earliest arrival until its
hold constraint is met. Each round is scored by the vyges-sta-si timer, and an
insertion is kept only if the worst hold slack improved and setup stays met — so a slow clock
with ample setup slack trades a little of it for hold closure, never the reverse.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom hold-fix demo # instant: close a two-flop hold violation
vyges loom hold-fix run top.holdfix -o fixed.v # delay → hold-fixed netlist
vyges loom hold-fix run top.holdfix --json # before/after WHS + WNS
vyges loom hold-fix run top.holdfix --fail-on-violation # exit 3 if hold still negative (CI gate)
vyges loom hold-fix check top.holdfix # validate the job
A .holdfix job is a superset of a vyges-sta-si .sta job (same design/netlist/lib/
clock or sdc/spef keys) plus the hold knobs: the buffer: (delay cell to insert),
hold_margin: (target hold slack), rounds: (low/medium/high), and dont_touch:.
See the full CLI reference (generated from --help).
Where it sits
routed netlist + .lib + .spef + constraints → hold-fixed netlist + before/after WHS and WNS.
A post-route ECO — with spef: present it scores the fix against real routed parasitics. It
decides which capture pins to delay and how deep a chain each needs; placement + routing of
the inserted cells is handed back to the flow. See the data spine.
Domain coverage
vyges-hold-fix inserts standard-cell delay/buffer cells on data paths in a gate-level
netlist, scored by the digital vyges-sta-si timer — it is digital
optimization. It does not apply to analog / mixed-signal blocks. For analog / MS physical &
integrity verification, see lvs, layout, em-ir,
thermal, and extract.
Source & releases
- Repo: https://github.com/vyges-tools/hold-fix
- Binaries: https://github.com/vyges-tools/hold-fix/releases
- Apache-2.0. Per-foundry calibration plugins are separate (NDA).
vyges-hold-fix — CLI reference
Generated from vyges-hold-fix --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-hold-fix — post-route hold-fix ECO (insert series delay on hold-violating capture pins)
usage:
vyges-hold-fix run JOB [-o OUT] [--json] [--fail-on-violation] hold-fix -> delayed netlist
vyges-hold-fix check JOB validate the job
vyges-hold-fix demo hold-fix a built-in example (no files)
flags:
-o FILE write the hold-fixed netlist to FILE (default: stdout)
--json emit the before/after report as JSON
--eco FILE write the ECO manifest (insertions) as JSON — for a physical applier
--fail-on-violation exit 3 if the result still has negative hold slack (CI gate)
-q, --quiet suppress non-essential output
-v, --verbose extra detail on stderr
--describe print a machine-readable JSON description of the command
-h, --help show this help
-V, --version show version
vyges-drc — design-rule check
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom drc. It’s also a standalonevyges-drcbinary on your PATH (the integration contract for flow authors).
vyges-drc answers the geometric half of physical verification: does the layout
obey the foundry’s rules? It reads a laid-out GDS and a small per-layer rule
deck and returns the list of violations. It is the geometric sibling of
vyges-lvs — LVS asks does the layout implement the schematic?, DRC asks does it
obey the rules? — and rides the same vyges-layout GDS/boolean/flatten kernel.
Run it
vyges install loom # one-time: fetch the Loom suite
vyges loom drc demo # built-in layout with violations
vyges loom drc check block.gds --rules sky130.drc # -> violations report
vyges loom drc check block.gds --rules sky130.drc --fail-on-violation # exit 3 (CI gate)
vyges loom drc fill block.gds --rules sky130.drc -o filled.gds # metal-fill generator
A rule deck keys on the GDS layer number; today’s classes are width,
spacing, area, windowed metal density, per-net antenna ratio, and
enclosure — plus a fill rule that drives the metal-fill generator
(vyges loom drc fill … -o out.gds):
# rule layer args
width 66 170 # min width on layer 66
space 68 140 # min spacing on layer 68
area 68 20000 # min polygon area (dbu²)
density 68 20 70 100000 # coverage on 68 must be 20–70% per 100000-dbu window
connect 5 68 # layers connect where they overlap (via/contact)
antenna 68 5 400 # per net: conductor area ≤ 400 × gate area
enclosure 68 66 40 # layer-66 shapes enclosed by layer-68 with ≥40 margin
fill 70 30 100000 600 400 # generate fill: top layer 70 to 30% per window
See the full CLI reference (generated from --help).
Where it sits
GDS + a .drc deck → violations (text or --json, with a CI exit code). It’s the
layout-rule check at sign-off, beside LVS. The deck is the plugin boundary: an
open reference deck ships for the open PDKs; a certified per-foundry deck stays
private under that foundry’s terms. Same-layer pre-merge is the next depth pass
on the same engine.
vyges-drc — CLI reference
Generated from vyges-drc --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-drc — geometric design-rule check (GDS/OASIS + rule deck -> violations)
usage:
vyges-drc check GDS --rules DECK [--top CELL] [-o OUT] [--json] [--fail-on-violation]
vyges-drc fill GDS --rules DECK [--top CELL] -o OUT.gds # metal-fill generator
vyges-drc demo [--json]
The input layout may be GDSII (.gds) or OASIS (.oas/.oasis) — picked by extension.
flags:
--rules DECK the .drc rule deck (required for `check` / `fill`)
--pdk NAME resolve the deck from pdk-store (drc_deck) instead of --rules
--top CELL top cell to flatten (default: the sole cell)
-o FILE write the report (or, for `fill`, the filled GDS) to FILE
--json machine-readable JSON instead of text
--fail-on-violation exit 3 when any violation is found (CI gate)
--views DIR render ranked violation views (PNG) into DIR — diagnostic evidence,
not sign-off; capped, and the number dropped is reported
--describe print a machine-readable JSON description of the command
-h, --help · -V, --version
vyges-cdc — clock-domain-crossing check
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom cdc. It’s also a standalonevyges-cdcbinary on your PATH (the integration contract for flow authors).
vyges-cdc finds the spots where a signal launched in one clock domain is captured
in another, and checks each is properly synchronized. It is a purely structural
graph analysis — which signals cross domains, and through what? — and notably a
question a lockstep gate-level simulator structurally cannot answer. It assigns each
flop a domain by tracing its clock pin to an SDC clock source, walks each capture
flop’s data cone to its launch flops, and reports every cross-domain pair.
Run it
vyges install loom # one-time
vyges loom cdc check design.v --lib cells.lib --sdc design.sdc # -> crossings report
vyges loom cdc check design.v --lib cells.lib --sdc design.sdc --fail-on-violation # exit 3
Each create_clock in the SDC is a clock domain; the Liberty identifies the flops
and their clock/data pins. A crossing is OK when it is a clean two-flop
synchronizer, and a violation when there is no synchronizer or combinational
logic sits on the crossing path.
See the full CLI reference (generated from --help).
Where it sits
Netlist + Liberty + SDC → the list of domain crossings (text or --json, with a CI
exit code). It’s an early structural lint that complements simulation — the
crossings sim can’t see. Handshake / gray-code recognition and reconvergence are the
depth passes.
vyges-cdc — CLI reference
Generated from vyges-cdc --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-cdc — structural clock-domain-crossing check
usage:
vyges-cdc check NETLIST --lib L.lib --sdc S.sdc [-o OUT] [--json] [--fail-on-violation]
flags:
--lib FILE Liberty (identifies flops + clock/data pins) — required
--sdc FILE SDC clock definitions (the domains) — required
-o FILE write the report to FILE (default: stdout)
--json machine-readable JSON instead of text
--fail-on-violation exit 3 if any unsynchronized crossing is found (CI gate)
--describe print a machine-readable JSON description of the command
-h, --help · -V, --version
vyges-glitch — static glitch / hazard analysis
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom glitch. It’s also a standalonevyges-glitchbinary on your PATH (the integration contract for flow authors).
vyges-glitch finds reconvergent-fanout hazards — the spots where one signal
reaches a combinational endpoint by more than one path and can momentarily glitch
before it settles. That is exactly what a lockstep gate-level simulator cannot
see: it samples one settled value per tick and steps over the intermediate glitch.
Catching it is a structural + timing question — parity from each Liberty arc’s
timing_sense, the glitch window from the same delay tables vyges-sta-si uses.
Run it
vyges install loom # one-time
vyges loom glitch check design.v --lib cells.lib # -> hazard report
vyges loom glitch check design.v --lib cells.lib --fail-on-violation # exit 3
A source reaching an endpoint by ≥2 paths is flagged static (the paths differ in inversion parity, so a single edge can drive the endpoint the wrong way for a moment) or dynamic (same parity, different delay — a glitch over the settling window). A balanced reconvergence is not flagged.
See the full CLI reference (generated from --help).
Where it sits
Netlist + Liberty → hazards (text or --json, with a CI exit code). It fills the
glitch blind spot of simulation and leans on the same timing data the STA engine
uses. SAT/BDD path sensitization and function hazards are the depth passes.
vyges-glitch — CLI reference
Generated from vyges-glitch --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-glitch — static glitch / hazard analysis (reconvergent fanout)
usage:
vyges-glitch check NETLIST --lib L.lib [-o OUT] [--json] [--fail-on-violation]
flags:
--lib FILE Liberty (cell parity via timing_sense + delays) — required
-o FILE write the report to FILE (default: stdout)
--json machine-readable JSON instead of text
--fail-on-violation exit 3 if any hazard is found (CI gate)
--describe print a machine-readable JSON description of the command
-h, --help · -V, --version
vyges-lec — combinational logic equivalence
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom lec. It’s also a standalonevyges-lecbinary on your PATH (the integration contract for flow authors).
vyges-lec answers: do two gate-level netlists compute the same function? It is
the formal sibling of simulation — a simulator shows two designs agree on the vectors
you ran; LEC proves they agree on all of them, or hands you the input where they
don’t. It builds a canonical ROBDD for every endpoint of both designs over one
shared variable order; equal functions share a node, so the check is exact, and a
mismatch’s miter walks straight to a counter-example.
Run it
vyges install loom # one-time
vyges loom lec check golden.v revised.v --lib cells.lib # -> verdict
vyges loom lec check golden.v revised.v --lib cells.lib --fail-on-diff # exit 3 if differ
vyges-lec — NOT EQUIVALENT ✗ (1 compared, 1 differ)
differ at `f` when a=1 b=0
Sequential designs are cut at the registers — flop Q nets are free inputs, flop D nets are endpoints — so it proves the combinational logic between registers (registers matched by name).
See the full CLI reference (generated from --help).
Where it sits
Golden + revised netlists + Liberty → an equivalence verdict (text or --json, with
a CI exit code). It guards every synthesis, ECO, and hand-edit. Gate functions come
from a standard-cell primitive map (an unknown cell is a hard error, never a silent
wrong answer); the Liberty function-attribute path and an AIG+SAT scaling path are
the depth passes.
vyges-lec — CLI reference
Generated from vyges-lec --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-lec — combinational logic equivalence check (golden vs revised)
usage:
vyges-lec check GOLDEN.v REVISED.v --lib L.lib [-o OUT] [--json] [--fail-on-diff]
flags:
--lib FILE Liberty (pin directions + comb/seq split) — required
-o FILE write the report to FILE (default: stdout)
--json machine-readable JSON instead of text
--fail-on-diff exit 3 if the designs are not equivalent (CI gate)
--describe print a machine-readable JSON description of the command
-h, --help · -V, --version
vyges-gds-view — headless GDS layout viewer
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom gds-view. It’s also a standalonevyges-gds-viewbinary on your PATH (the integration contract for flow authors).
vyges-gds-view renders a laid-out GDS to a single self-contained SVG — every
shape coloured by its layer, a layer legend, the Y axis flipped so up is up — with an
optional violation overlay. Where vyges-drc and vyges-lvs tell you what is
wrong, this shows you where: render the GDS, drop the violation coordinates on top,
open it in any browser, commit it to a report, or diff it in CI. No display server,
no GUI toolkit; it rides the same vyges-layout kernel.
Run it
vyges install loom # one-time
vyges loom gds-view demo -o demo.svg # built-in sample layout
vyges loom gds-view render block.gds -o block.svg # flatten top cell -> SVG
vyges loom gds-view render block.gds --marks viols.txt -o block.svg # overlay violations
The marks file is one violation per line — x0 y0 x1 y1 [label] in GDS db units
— the trivial format any engine can emit, so a DRC-then-look pass is two commands.
See the full CLI reference (generated from --help).
Where it sits
GDS (+ optional violation marks) → a layered SVG. It’s the visual companion to the geometry engines — the headless, mask-level renderer for reports and CI, distinct from any interactive block-level explorer. Datatype colour keys and hierarchical views are the depth passes.
vyges-gds-view — CLI reference
Generated from vyges-gds-view --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-gds-view — headless layout viewer (GDS or OASIS in, layered SVG out)
usage:
vyges-gds-view render LAYOUT [--top CELL] [--layers L1,L2] [--marks FILE] [-o OUT.svg]
# LAYOUT is GDSII (.gds) or OASIS (.oas/.oasis) — picked by extension
vyges-gds-view demo [-o OUT.svg]
flags:
--top CELL top cell to flatten + render (default: last cell in the GDS)
--layers LIST comma-separated GDS layer numbers to show (default: all)
--marks FILE overlay violation boxes; each line: `x0 y0 x1 y1 [label...]`
-o FILE write to FILE (default: stdout). SVG, or a PNG if FILE ends in .png
--png force PNG (bounded raster thumbnail — for dense real blocks)
--width N PNG fit size in pixels (default: 700)
--window BOX PNG only: frame this db-unit region instead of the whole cell,
as `x0,y0,x1,y1` — the occurrence-level view for one violation
--describe print a machine-readable JSON description of the command
-h, --help · -V, --version
vyges-meas — closed measurement kernels
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom meas. It’s also a standalonevyges-measbinary on your PATH (the integration contract for flow authors).
vyges-meas answers: what does this capture actually measure? Two families of scalars —
coherent single-tone SNR, SINAD, THD, SFDR from a captured time series, and gain,
bandwidth, unity-gain frequency, phase margin from an AC sweep.
Why the definition is the product
SNR names a ratio, not a measurement. Whether the fundamental is excluded from noise, how many
harmonics are counted, whether DC is in the band, where the band ends, what happens to a harmonic
that aliases back below Nyquist — every one of those changes the number, and two honest tools can
differ by several dB while both being “right”. A converter datasheet is comparable to a
simulation only if both state the same choices.
So each kernel fixes one method, documents every choice, and refuses inputs it cannot measure that way. A refusal is a result: it says the number would have been meaningless.
Run it
vyges install loom # one-time
# spectral — one scalar per call, each independently checked
vyges loom meas spectral capture.samples --fundamental-bin 37 \
--metric thd --harmonics 2,3,4,5
# AC transfer
vyges loom meas transfer opamp.ac --metric phase-margin --target 45
SERIES is one sample per line in capture order. SWEEP is hz gain_db phase_deg per line,
strictly increasing. Both accept # comments. Add --json for machine output; -o FILE writes
a report while the JSON still goes to stdout, so asking for the file never costs you the parsed
result.
The spectral method
| choice | this kernel |
|---|---|
| record length | power of two, 8 to 65,536 samples |
| sampling | coherent — the fundamental lands exactly on a DFT bin, and you say which |
| window | none. A rectangular window is exact for a coherent capture and wrong otherwise, so a non-coherent capture is refused, not smeared |
| DC | the mean is removed and the DC bin is excluded from every partition |
| harmonics | folded into the first Nyquist zone — an aliased harmonic’s power is really in the record |
| integration width | zero bins: each component is exactly one bin, never a skirt |
| collisions | a harmonic landing on DC, the fundamental, or another harmonic is refused — counting one bin twice would double-count its power |
| clipping | a clipped record is refused: it describes the acquisition, not the device |
SNR = 10 log10(p_f / p_n) noise only, declared harmonics excluded
SINAD = 10 log10(p_f / p_r) everything that is not the fundamental
THD = 10 log10(p_h / p_f) harmonics against the fundamental (negative dB)
SFDR = 10 log10(p_f / p_s) distance to the worst single spur
The AC method
Values between swept points are interpolated in (log10 f, dB) and (log10 f, degrees) — the space these are plotted in, so a coarse sweep does not read low. Nothing is extrapolated: a crossing outside the swept range is reported as absent, because a sweep that stopped too early is a fixable mistake and a guessed number is not.
Bandwidth is referenced to the peak gain, not the first point. A response that peaks before rolling off has its −3 dB corner relative to that peak, and referencing the first point would be wrong for exactly the circuits where the number matters most.
The verdict
With --target, the result carries a pass/fail: SNR, SINAD, SFDR and the AC metrics want
at least the target; THD wants at most it. Without a target there is no claim to make, so
met is null and the result envelope reports unknown rather than a pass
nobody asked for.
A refused input also resolves to unknown — the engine ran, and the evidence does not support a
conclusion.
How much a result claims
A number and a standard’s name printed near each other read as a conformance claim whether or not one was meant. So every result carries a machine-readable statement of exactly how much it claims:
| level | means |
|---|---|
vyges-definition | the method is ours, complete and versioned. No external standard is claimed. |
candidate | the application lies inside a named standard’s published scope, but no clause-level review has been done |
reviewed | a crosswalk records the exact edition, clauses, choices, deviations, reviewer and artifact |
conformant | an independently reviewed profile and a conformance suite |
--application decides which scope a result may name. It defaults to generic, because the tool
cannot infer from a list of numbers what device produced them and guessing would manufacture a
standards claim out of nothing:
--application | reaches | against |
|---|---|---|
generic (default) | vyges-definition | — |
adc | candidate | IEEE 1241-2023 |
dac | candidate | IEEE 1658-2023 |
recorder | candidate | IEEE 1057-2017 |
"alignment": {
"level": "candidate",
"edition": "IEEE 1241-2023",
"application": "adc",
"statement": "candidate (IEEE 1241-2023) — … NO clause-level review has been performed, so this is not a conformance claim"
}
The ladder is enforced, not merely documented. reviewed and conformant can only be built
from a crosswalk, and a crosswalk cannot exist without every field of the evidence it stands for —
edition, clauses, choices, deviations, reviewer, artifact. A claim stronger than the evidence has
no constructor. Nothing here is reviewed or conformant, and nothing becomes so by editing
a label.
The published scopes of those editions are the limit of what is asserted; the normative clauses
needed for a conformance claim are not public, so candidate is the honest ceiling today.
IEEE 519 is not authority here. It governs harmonic control in electric power systems at a point of common coupling — a different quantity, measured elsewhere, for a different purpose. A THD figure from this engine must never be cited as 519-anything. Common enough on datasheets that the exclusion is recorded in code.
vyges-meas — CLI reference
Generated from vyges-meas --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-meas — closed measurement kernels (coherent single-tone spectral, AC transfer)
usage:
vyges-meas spectral SERIES --fundamental-bin N --metric snr|sinad|thd|sfdr
[--harmonics 2,3,4,5] [--clip LEVEL] [--target DB]
vyges-meas transfer SWEEP --metric gain|bandwidth|unity-frequency|phase-margin
[--target VALUE]
vyges-meas demo measure a synthesized coherent tone (no input files)
SERIES is one sample per line, in capture order. The record must be a power of two
between 8 and 65536 samples and must be COHERENTLY sampled: the fundamental has to
land exactly on a DFT bin, and --fundamental-bin says which. There is no window
function — a rectangular window is exact for a coherent capture, and a non-coherent
one is refused rather than silently smeared.
SWEEP is `hz gain_db phase_deg` per line, strictly increasing in frequency. Values
between points are interpolated in (log10 f, dB); nothing is extrapolated past the
swept range.
Every choice the method makes is documented in `vyges-meas --describe` and in the
module docs. These are Vyges definitions, NOT a claim of IEEE 1241/1658/1057
conformance.
flags:
--fundamental-bin N DFT bin the fundamental sits on (spectral; required)
--metric M which scalar to measure (required)
--harmonics LIST harmonic orders to account for, e.g. 2,3,4,5 (spectral)
--clip LEVEL treat |sample| >= LEVEL as clipped and refuse to measure
--application WHAT what the record measures: generic (default) | adc | dac | recorder.
Declaring it is what lets the result name a standard's scope; the tool
cannot infer from a list of numbers what device produced them, and
guessing would manufacture a standards claim out of nothing.
--target VALUE pass/fail threshold; SNR/SINAD/SFDR/gain want >= , THD <=
-o FILE write the report to FILE (default: stdout)
--json machine-readable JSON instead of the text report
--describe print a machine-readable JSON description of the command
-h, --help · -V, --version
vyges-remap — multi-output technology re-mapping
Part of the Vyges Loom suite. Install once with
vyges install loom, then runvyges loom remap. It’s also a standalonevyges-remapbinary on your PATH (the integration contract for flow authors).
vyges-remap answers: can this netlist be mapped better using cells a single-output mapper
cannot reach? Given an AIGER netlist (or Verilog RTL, from which Yosys extracts one) and a
technology genlib, it runs a single-output baseline and a multi-output pass, writes the remapped
Verilog, and reports the before/after cell and area delta — including how many multi-output cells
(adders, compressors) were mapped that a single-output mapper would have missed.
Run it
vyges install loom # one-time
vyges loom remap emap --verilog design.v --top top --genlib cells.genlib -o mapped.v
Every remap is gated by an equivalence check
A transform that changes the netlist has to prove it did not change the function. After mapping,
remap runs an ABC combinational equivalence check of the mapped netlist against the input
AIG. A failed check makes the run an error, and the netlist is rejected rather than handed on.
The verdict is tri-state, and the middle state matters:
equivalent | when |
|---|---|
true | the check ran and the mapped netlist is equivalent |
false | the check ran and it is not — the remap is rejected |
null | the check did not run (--no-cec) or ABC was inconclusive |
null resolves to unknown in the result envelope. A remap that was not
checked is not a remap that is correct — nothing has established that the mapped netlist still
computes the input function, and a consumer reading only the execution status would see ok for
an unverified transform. That conflation is exactly what the two status axes exist to prevent.
Provenance
The mapping and the equivalence check are performed by external emap, abc and yosys binaries
resolved at run time. Their versions are not part of input_hash, so the same arguments can
produce a different result under a different toolchain build — the engine declares this in its
descriptor, and it travels with every result as provenance.limitations.
vyges-remap — CLI reference
Generated from vyges-remap --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-remap — file-level multi-output technology re-mapping (mockturtle emap)
usage:
vyges-remap emap (--verilog <d.v> --top T | --aig <a.aig>) (--genlib <g> | --liberty <lib>) [-o out.v] [--no-cec] [--json]
vyges-remap --describe structured tool contract (for `vyges mcp`)
vyges-remap --version | --help
Extracts an AIG (Yosys, from --verilog) or takes one (--aig), then runs the
vyges-emap driver twice (single-output baseline + multi-output) and reports the
before/after cell/area delta. Tools resolve via $VYGES_EMAP / $VYGES_YOSYS / $VYGES_ABC.
vyges-layout — the geometry kernel
Foundation, not a sign-off engine.
vyges-layoutis the layout geometry kernel the other layout-side tools ride on — it does not produce a sign-off verdict or standard artifact the way the Loom engines do, and it’s not promoted as avyges loomsubcommand (it’s an internal foundation, used as a standalonevyges-layoutbinary). It’s listed here because it’s the substrate beneath the suite.
Everything on the layout side is geometry: LVS device extraction (GDS → devices + nets),
DRC (width / spacing), metal fill, and viewing a die — they all need to read GDSII, do
boolean operations on shapes, and flatten hierarchy. vyges-layout is that shared
base: a clean-room, memory-safe Rust kernel, std-only and auditable, peer to KLayout’s
database and gdstk (which are excellent but C++). It is the dependency that unblocks
vyges-lvs native GDS extraction, and the future DRC, fill, and chip viewer.
Run it
vyges-layout info block.gds # cells, layers, areas, bbox (+ --json)
vyges-layout boolean block.gds --top top --op and --a 67/20 --b 68/20 --out 100/0 -o and.gds
vyges-layout flatten block.gds --top top -o flat.gds
vyges-layout demo # built-in, no files
See the full CLI reference (generated from --help).
What it does (v0)
- GDSII read/write — round-trips a library (BOUNDARY / PATH / SREF / AREF / BOX).
info— cells, per-cell element counts, layers, per-layer area — text or JSON.- boolean — AND / OR / NOT / XOR between two layers via a vertical scanline on rectilinear (Manhattan) polygons; integer coordinates → exact.
- flatten — expand SREF / AREF hierarchy into one cell (composed transforms, arrays, cycle-guarded).
Honest bounds. v0 boolean is Manhattan — exact for any rectilinear polygon, returned as a set of tiling rectangles (contour-tracing into merged polygons is depth); general-angle geometry is bbox-approximated and counted, never silently dropped. General clipping (Vatti) is the depth pass.
Digital and analog / mixed-signal
The kernel has zero digital-vs-analog notion — it operates on raw GDS layers, datatypes
and polygons, not on standard cells or any clocked abstraction. So an analog / mixed-signal
layout round-trips and booleans exactly as a digital one does. The examples/analog/ fixture
proves it on the shapes an analog designer actually draws — a guard ring (a donut polygon), a
MIM capacitor (two overlapping plates on different layers), and a poly resistor snake — and
tests/analog.rs checks exact write→read round-trip plus a cross-layer boolean (top-plate AND
bottom-plate = the MIM cap area).
cargo run --example gen_analog # generate examples/analog/analog.gds
vyges-layout info examples/analog/analog.gds # cells, layers, areas — analog block
vyges-layout boolean examples/analog/analog.gds --top analog --op and --a 66/20 --b 65/20 --out 100/0 -o mim.gds
The Manhattan / rectilinear bound noted above is geometric, not domain-related — it applies to digital and analog shapes alike. Scope here is physical geometry; analog functional / timing sign-off is out of scope (that leans on external SPICE / behavioral tools).
Source & releases
- Repo: https://github.com/vyges-tools/layout
- Binaries: https://github.com/vyges-tools/layout/releases
- Apache-2.0.
vyges-layout — CLI reference
Generated from vyges-layout --help. Do not edit by hand — run scripts/gen-cli-reference.sh.
vyges-layout — layout geometry kernel (GDSII + OASIS read/write, boolean ops, flatten)
usage:
vyges-layout info LAYOUT [--json]
vyges-layout boolean LAYOUT --op and|or|not|xor --a L/D --b L/D --out L/D -o OUT [--top C]
vyges-layout flatten LAYOUT --top CELL -o OUT
vyges-layout demo
LAYOUT / OUT may be GDSII (.gds) or OASIS (.oas/.oasis) — the format is picked by
extension, so the tools double as a GDS↔OASIS converter. `L/D` is layer/datatype,
e.g. 68/20. `boolean` operates on one cell's own shapes (flatten first for
hierarchy); v0 boolean is Manhattan (axis-aligned rectangles).
flags:
--op OP and | or | not (A−B) | xor
--a L/D first layer/datatype --b L/D second layer/datatype
--out L/D output layer/datatype --top C cell to operate on
-o FILE output GDS / report file
--json machine-readable output (info)
-q/--quiet · -v/--verbose · -h/--help · -V/--version
--bug-report · --feature-request · --sponsor · --star ⭐
vyges-events — structured events & logging
Foundation, not a sign-off engine.
vyges-eventsis the shared structured-event and logging contract that every Loom engine emits — and the substrate the MCP layer and cross-stage analysis consume. Likevyges-layoutit’s a foundation crate, not a promotedvyges loomsubcommand.
In an LLM/MCP-driven flow you need a queryable trail of what each tool did and why, so a
late failure can be traced back to its early cause. vyges-events is that trail: each engine
emits one structured vyges-events/1.0 event per finding, plus a completion event, on
stderr, as newline-delimited JSON. The report/data on stdout is never touched.
Logs and events are one path
A plain log line is just an event with no code/objects. The same records render two ways,
controlled by two environment knobs:
| Variable | Effect |
|---|---|
VYGES_LOG=<level> | severity filter — trace|debug|info|warn|error (default info) |
VYGES_LOG_FORMAT=json|text | force the rendering; default auto — human text at a terminal, JSONL when piped |
vyges-drc check block.gds --rules deck.rules # report → stdout; events → stderr
# at a terminal: [WARN vyges-drc DRC-WIDTH] width < min on layer 66 [layer:66]
# when piped: {"schema":"vyges-events/1.0",…,"code":"DRC-WIDTH","objects":["layer:66"]}
VYGES_LOG=error vyges-drc check block.gds --rules deck.rules # only errors on stderr
The event
| Field | Meaning |
|---|---|
schema | always vyges-events/1.0 |
ts_ms | unix epoch milliseconds |
tool | emitting engine (vyges-drc, vyges-lvs, …) |
severity | trace/debug/info/warn/error |
code | structured code (DRC-WIDTH, LVS-MISMATCH, …) — the clustering key |
objects | design objects named (net:data[3], cell:sram0, layer:66) — the cross-stage co-reference key |
raw_msg / msg_template | the message (full / with variable parts masked) |
run_id / step_index / stage | orchestration context (stamped by the runner) |
file | source location, if applicable |
The full JSON Schema is self-published by the crate — dump it with vyges-events --schema.
How it flows (the causal trail)
- Engines emit events on stderr.
- The MCP layer (
vyges mcp/vyges model) parses them into theloom-resultenvelope’slogsblock (a compact summary — counts by severity, the codes seen — plus the events), and streams each line live as an MCPnotifications/messagewhile a long tool call runs, so you see progress instead of a capture-at-end blob. - A
vyges modelrun aggregates every step’s events into~/.vyges/runs/<run_id>/events.jsonl— one ordered event stream across the whole multi-step flow, each event stamped with itsrun_idandstep_index.
Because every event carries the design objects it touched, a late failure (e.g. a routing
DRC error) can be linked back to the early event that caused it (e.g. a synthesis warning on
the same net) — cause to effect, across stages.
For engine authors
Depend on the crate (vyges-tools/events, Apache-2.0) and emit via standard tracing macros:
#![allow(unused)]
fn main() {
tracing::warn!(code = "DRC-0142", objects = "net:data[3],macro:sram0", "spacing < min");
}
or build an Event directly. See the crate README for the tracing bridge and the sink
(default: JSONL on stderr). Emission is daemonless — each engine writes locally; the
orchestrator aggregates.
Job-file formats
Every engine is driven by a small declarative job file — you describe the job,
not the script. Each format is documented with worked examples in its engine’s
repository (the examples/ directory, linked from each engine’s chapter).
Sign-off · analyze — describe the job, get a standard sign-off artifact:
| Format | Engine | Declares |
|---|---|---|
.char / .charlib | vyges-char | corner(s), cells, SPICE collateral |
.ext | vyges-extract | design, PDK parasitic rules, settings |
.pwr | vyges-power | netlist, libraries, activity source, budget |
.sta | vyges-sta-si | libraries, parasitics, constraints |
.emir | vyges-em-ir | design, PDN, IR/EM budget |
.thermal | vyges-thermal | die + grid + material params, floorplan, limit |
.lvs | vyges-lvs | layout (GDS) + schematic netlist |
Optimizers · act — netlist in, better netlist out (each move scored by sta-si):
| Format | Engine | Declares |
|---|---|---|
.resize | vyges-resize | netlist, libraries, (SPEF), timing / area goal |
.vtswap | vyges-vt-swap | netlist, libraries, (SPEF), leakage / timing goal |
.bufins | vyges-buffer-insert | netlist, libraries, (SPEF), transition limit |
Shared CLI conventions
Every engine shares the same surface (<engine> = vyges loom <name>, e.g.
vyges loom sta-si):
vyges loom <engine> run JOB [-o OUT] [--json] run the job → standard artifact (or JSON)
vyges loom <engine> check JOB parse + validate the job
vyges loom <engine> demo built-in example, no inputs
Common flags: --json, -q/--quiet, -v/--verbose, -h/--help, -V/--version,
plus the central --bug-report / --feature-request / --sponsor. The engines that
gate on a budget/limit add a fail flag — sta-si, em-ir, thermal use
--fail-on-violation; power uses --fail-on-budget — returning a distinct non-zero
exit code so a violation fails CI automatically.
-V/--version prints the exact build commit (e.g. vyges-char 0.0.1 (abc1234))
so a bug report traces back to a precise build.
Integrating the engines into a flow
The engines are the Vyges Loom suite — end users run them as vyges loom <engine> after a
one-time vyges install loom. Under the hood each is a standalone binary that cooperates by
handing the next one standard files (Liberty, SPEF, SPICE) — see the data spine.
This page is for tool and flow authors (OpenROAD / LibreLane / OpenLane 2 / custom
orchestrators): where each engine plugs in, and how to call it directly as a binary (the
leanest integration — no vyges front door required).
Where each engine plugs into an OpenROAD / LibreLane flow
There is no single integration point — each engine is a drop-in second opinion / alternative at its own stage:
| Engine | Flow stage | Sits beside (OSS) | Adds |
|---|---|---|---|
vyges-char | cell characterization (upstream) | Liberate | a .lib when you don’t already have one |
vyges-extract | parasitic extraction (post-route) | OpenRCX | coupling-aware SPEF (the SI input) |
vyges-power | power analysis (post-synth / post-route) | OpenSTA report_power | leakage + dynamic, and the activity map em-ir needs |
vyges-sta-si | static timing (signoff) | OpenSTA | SI/crosstalk + statistical (AOCV/POCV-LVF) OCV |
vyges-em-ir | power integrity (PDN) | PDNSim | IR-drop / EM second opinion |
vyges-lvs | layout-vs-schematic (signoff) | Netgen | MATCH/MISMATCH with the divergence named; native GDS extraction |
“Just integrate sta-si?” Start there — it’s the highest-value single drop-in (the SI-aware
timing answer base OpenSTA can’t give). Then adopt the rest à la carte, each at its own stage —
not “through sta-si”: extract deepens sta-si’s SI with coupling SPEF; power feeds both a power
number and em-ir; em-ir is parallel (power integrity, not timing); lvs is layout-correctness at
sign-off; char only if you lack a .lib.
Already on OpenLane / LibreLane? Drop these in.
These are sign-off engines, not another flow — single std-only binaries, seconds not stages, no nix store and no 60-stage orchestration just to sanity-check timing. You keep running LibreLane for place-and-route; you just enter it cleaner and verify its output with a faster, more legible checker. Because their inputs differ, they sit at two points:
Right after Yosys (pre-P&R) — shift the gate left. Catch a broken constraint, a timing wall, or a power problem before you spend an hour in P&R, so you re-spin the heavy flow fewer times.
| Engine | Runs on | Catches early |
|---|---|---|
vyges-sta-si | synth netlist + .lib + SDC | broken constraints, a timing wall, bad clock setup |
vyges-power | synth netlist + .lib + VCD/vectorless | a power / activity problem while it’s still cheap to fix |
After the flow produces layout — independent fast sign-off. Run on LibreLane’s own DEF/GDS for a second opinion — faster than re-spinning the flow, and it names what diverges.
| Engine | Runs on | Role |
|---|---|---|
vyges-extract | routed DEF | SPEF — second opinion vs OpenRCX (0.997 on a routed block) |
vyges-sta-si | netlist + real SPEF | post-route timing with the actual parasitics |
vyges-em-ir | PDN + currents | IR-drop / electromigration |
vyges-lvs | extracted GDS + schematic | MATCH / MISMATCH with readable diagnostics vs Netgen |
Be precise about “faster convergence.” These don’t touch LibreLane’s optimizer, so they don’t
make P&R itself faster. The honest mechanism is two-fold, and both are real: (1) cleaner entry →
fewer expensive flow spins — catching a broken SDC or a timing/power wall post-Yosys means you
don’t discover it 50 minutes into P&R and re-spin; (2) an independent verdict that catches what
the flow’s own tools miss or report cryptically (vyges-lvs vs Netgen, vyges-extract vs OpenRCX,
vyges-sta-si vs OpenSTA). char isn’t in this loop — it builds libraries, not per-design checks.
Three ways to integrate — leanest first
0. Direct binary — no Python, no TCL (recommended for new / upstream integration)
Every engine is a plain binary: a declarative job in, the standard artifact + JSON out, a CI-gating exit code. Any tool, any language, just shells out:
vyges-sta-si run timing.sta --json # → {"wns_ns": -0.05, "tns_ns": -0.2, ...} exit 3 if WNS<0
vyges-extract run top.ext # → SPEF
vyges-char run cells.char # → Liberty .lib
vyges-em-ir run top.emir # → IR/EM report
No plugin, no interpreter, no linking — the binary is the contract.
1. An adapter for the incumbent’s script format (where one exists)
For teams with existing scripts: e.g. vyges-sta-si ships an experimental OpenSTA-TCL-subset
adapter (vyges-sta-si tcl script.tcl) so an existing OpenSTA script runs through the engine with
zero rewrite. (See the sta-si repo’s docs/opensta-integration.md.)
2. An orchestrator step — for native flow metrics
For LibreLane flows that want the result as native metrics next to OpenSTA’s, the sta-si repo ships
a LibreLane plugin Step (integrations/librelane/) that reads the flow State and emits
vyges__… metrics — the SI second opinion becomes a metric comparison. (Longer term these land in
the Sley orchestrator.)
We want to help
Integrating a Vyges engine directly into your tool — and have a question, a missing job-file field, or a JSON-schema tweak you need? We’re happy to help and to shape the interface to your flow. Reach us at https://vyges.com/contact.
Deeper, per-engine integration docs (the OpenSTA boundary, the LibreLane step, the full cross-engine map) live in each engine’s repository under
docs/andintegrations/— linked from that engine’s chapter above.
Tool descriptor — --describe
Every Vyges engine can describe itself: run vyges-<engine> --describe and it prints one
JSON object saying what it is, how to call it, what it produces, and what claim its result may
establish about your design.
vyges-drc --describe
One probe is enough to drive an engine you have never seen. That is what lets
vyges mcp hand an AI IDE a typed tool for each engine — real per-parameter
schemas rather than an opaque argument string — and it is equally usable from your own
orchestrator, CI job, or script.
The descriptor is emitted by the binary, so it cannot drift from the code that implements it. If an engine gains a flag, its descriptor gains it in the same build.
Who this page is for: anyone driving the engines programmatically — flow authors, orchestrators, CI, and agent tooling. If you just want to run an engine by hand,
--helpis the friendlier surface.
A complete descriptor
This is the real output of vyges-em-ir --describe:
{
"name": "em-ir",
"summary": "EM / IR-drop power-integrity sign-off (PDN -> report)",
"maturity": "workflow-validated",
"provenance_limitations": [
"The job names the PDN or DEF/LEF and any power and decap maps; input_hash covers the job path and arguments, not their contents."
],
"invocation": {
"args_template": ["run", "{job}"],
"optional": [ { "arg": "out", "flag": "-o" } ],
"emits_json": true
},
"inputs": {
"type": "object",
"required": ["job"],
"properties": {
"job": { "type": "string", "description": "Path to the EM/IR-drop job file (PDN + limits)." },
"out": { "type": "string", "description": "Write output to FILE instead of stdout." }
}
},
"artifacts": [ { "role": "emir_report", "field": "report_path" } ],
"assertion": {
"id": "power-integrity-met",
"field": "pi_met",
"pass_when": { "is_true": true }
},
"consumes": ["pdn", "power_report", "spef", "emgeom"]
}
Given only that, a caller can build the command, validate arguments before spending a run, find the report afterwards, and read a pass/fail verdict — without knowing anything else about power integrity.
Top-level fields
| Field | Required | What it is |
|---|---|---|
name | yes | Stable tool id (drc, sta-si, …). The MCP tool takes this name. |
summary | yes | One line, shown as the tool’s description. |
invocation | yes | How to build the command — see below. |
inputs | no | JSON Schema for the callable parameters. Defaults to an empty object schema. |
artifacts | no | The files the run produces, and how to locate them. |
assertion | no | How to derive the engineering verdict. Omitted → the result is unknown. |
maturity | no | How far the evidence has been proven. Omitted → discovered, which suppresses the verdict. |
provenance_limitations | yes | What input_hash does not cover, in the engine’s own words. |
consumes | no | Input artifact roles the engine expects (e.g. ["netlist","liberty","spef"]). Declarative today — published for flow authors, not interpreted by the CLI. |
A payload without a usable invocation.args_template is not a descriptor; callers should fall
back to passing raw CLI arguments.
invocation — building the command
"invocation": {
"args_template": ["check", "{gds}", "--rules", "{deck}"],
"optional": [ { "arg": "top", "flag": "--top" } ],
"emits_json": true
}
args_template— the argument vector. A{name}token is substituted with the caller’s value forname. Tokens are required: a missing one is a caller error, not a default.optional— appended only when supplied. Withflag, the pair--top TOPis appended; without one, the bare value is appended.emits_json— when true (the default), callers append--jsonif it is not already present, so the engine’s machine-readable output comes back.
For the descriptor above, {job: "block.emir", out: "emir.rpt"} builds:
vyges-em-ir run block.emir -o emir.rpt --json
inputs — the parameter schema
A standard JSON Schema object describing the callable parameters. vyges mcp passes it through
as the MCP tool’s inputSchema, which is why an engine’s parameters appear individually named
and documented in an AI IDE. Use it to validate a call before running anything.
Keep name and inputs in mind as the compatibility surface: changing either changes how every
existing caller must invoke the tool.
artifacts — finding what the run produced
Each entry names a role and says where the path comes from:
"artifacts": [
{ "role": "timing_report", "field": "report_path" }, // path comes from the engine's --json
{ "role": "sdf", "from_arg": "sdf" } // path is the value of an input argument
]
An entry needs a source. role alone says a file exists but not where to find it, so the
registry drops it — the role then has no effect and the file never appears in the result. Pair
every role with a field or a from_arg, and expose the output argument in invocation.optional
so a caller can ask for it in the first place.
Prefer field for anything the engine writes. A sign-off engine given -o FILE reports the
path back as report_path in its --json, so the artifact is located from the result rather
than by echoing an input. That also means the payload still arrives on stdout when -o is used —
-o writes the report, it does not redirect the machine output — so one call yields both the
verdict and the artifact. Use from_arg where the path really is just an input the engine wrote
to and does not echo back (sta-si’s --sdf, for instance).
| Key | Meaning |
|---|---|
role | What the file is — drc_report, timing_report, lvs_report, netlist, svg, … |
field | Key in the engine’s --json output holding the path. |
from_arg | Input-argument name whose value is the path (for -o-style outputs). |
Roles are not just labels. vyges mcp derives a tool’s read-only vs mutating classification
from them — an engine that produces a netlist edits your design, one that produces a
drc_report does not — which is what the VYGES_MCP_PROFILE tiers gate on. See
read-only vs mutating tools.
assertion — the design verdict
An engine run has two independent outcomes: whether the process succeeded, and what the
evidence says about your design. assertion declares how to derive the second from the
engine’s own --json output.
"assertion": {
"id": "drc-clean", // stable name for the claim
"field": "clean", // key in the engine's --json output
"pass_when": { "is_true": true },
"summary_field": "summary" // optional: a human-readable line to surface
}
pass_when | Passes when the field is |
|---|---|
{ "is_true": true } | boolean true |
{ "eq": <value> } | equal to that value (numbers compare numerically) |
{ "lte": <number> } | a number less than or equal to it |
Alternatively { "id": "...", "not_applicable": true } declares that the operation makes no
engineering claim — a viewer or format converter — which is different from having one and not
reaching it.
The derived verdict lands in the loom-result envelope as engineering.status
(pass | fail | unknown | not_applicable), separate from the execution status — see
the result envelope. The rules
are deliberately conservative: no declared assertion, a run that did not complete, or a verdict
field that is missing, null, or the wrong type all yield unknown — never pass, and never
fail. Nothing is reported as passing on absent evidence, and a tooling defect is never
reported as a design defect. See the two status axes.
Declaring one well
The verdict field must cover the whole check. Two traps are worth naming, because both occurred in this suite and both would have overstated the result:
- A partial verdict. Timing has setup and hold; power integrity has IR drop and electromigration. Asserting on a field that covers only one half passes designs that fail the other. Where an engine reports several partial verdicts, assert on a combined field.
- A genuinely inconclusive state. Some checks can finish without reaching a conclusion — a
layout-vs-schematic MATCH the bounded search could not confirm, or a timing run with no
endpoints to analyze. Emit the verdict field as
nullin those cases rather than forcing a boolean;nullresolves tounknown, which is the honest answer.
maturity — how far the evidence has been proven
Separate from what a verdict says is how much it can be relied on. maturity is that second
axis, and it is deliberately about the engine, not the design.
| Level | Means |
|---|---|
discovered | The binary resolves and reports a version. Nothing about its output is guaranteed. |
structured | It publishes a versioned operation and a normalized result — a descriptor like this one. |
workflow-validated | Its repository additionally carries a pinned design or fixture that the test suite runs end to end and asserts against, so the operation is proven on a real input, not merely described. |
It gates the verdict, it is not decoration. At discovered there is no validated result shape
behind an assertion, so the claim is not reported — engineering.status stays unknown however
well-formed the assertion is. Absent or unrecognized means discovered: an engine has to say more
to claim more, the same principle as an absent assertion.
The level also rides along in the generated MCP tool description, so an agent weighing a result sees it without a second call.
Where the Loom engines stand
Published because publishing your own gaps is the point — a ladder nobody is ever on the bottom rung of would say nothing.
| Level | Engines |
|---|---|
workflow-validated | sta-si · em-ir · lvs · extract · thermal · power |
structured | drc · cdc · glitch · lec · char · gds-view · resize · vt-swap · buffer-insert · hold-fix |
The structured engines are not less correct — several carry substantial unit-test suites. They
simply do not yet ship a pinned end-to-end case in-repo, and the ladder reports what is proven
there, not what is believed.
provenance_limitations — the boundary of the hash
Required. Every descriptor must state what input_hash does not cover.
The reason it is required rather than encouraged: the boundary is easy to leave implicit and
expensive to discover later. input_hash is taken over the resolved binary identity, version,
declared environment and the argument vector — not the content of any file those arguments
name, and not anything those files in turn reference. A job file that points at a netlist, a
Liberty and a SPEF contributes only its own path to the hash. Edit the netlist in place and the
hash does not move.
"provenance_limitations": [
"The job names the netlist, Liberty and SPEF; input_hash covers the job path and arguments, not their contents, and Liberty `include` files are not enumerated."
]
The declared strings travel with the evidence they qualify — they appear as
provenance.limitations in every result envelope, beside the input_hash they
are about, so a consumer reads the caveat where it matters rather than having to go looking for it.
Stability
A descriptor carries no version of its own — it is whatever the binary you invoked emits, so
pin the engine version if you need a fixed contract (vyges-<engine> --version).
name and inputs form the compatibility surface: treat a change to either as a breaking change
for callers. New optional fields may appear over time — ignore what you do not recognize, and
never infer a passing verdict from a field you cannot interpret.
Result envelope — loom-result
Every engine invocation made through vyges mcp returns the same JSON object,
whatever the engine. One shape to parse, whether you called DRC, timing, or a layout viewer —
and a failure comes back in that shape too, never as a crash.
Where the tool descriptor says how to call an engine, this says what comes back.
Note: engines invoked directly on the command line print their own
--jsonpayload. The envelope is added by the layer that runs them, and the engine’s own output is carried inside it verbatim asresult.
A complete envelope
Real output from a vyges-em-ir run, abridged only where marked:
{
"schema": "loom-result/1.1",
"tool": "em-ir",
"tool_version": "0.1.15",
"status": "ok", // did the PROCESS run?
"engineering": { // what does the evidence say about the DESIGN?
"status": "pass",
"assertion": "power-integrity-met",
"summary": "assertion 'power-integrity-met' held on 'pi_met'"
},
"input_hash": "blake3:f81c6c0221446a1296d4541fa732e433517e759b6480a612d6dda769f7c3f3f7",
"result": { /* the engine's own --json output, verbatim */ },
"artifacts": [
{ "role": "emir_report", "path": "emir.rpt",
"hash": "blake3:9f2a4c1e7b3d8056a1c4f9e2b7d05384c6a1f9e2b7d05384c6a1f9e2b7d05384" }
],
"error": null,
"logs": {
"count": 1,
"events": [ /* vyges-events records */ ],
"summary": { "info_count": 1, "codes": ["EMIR-DONE"] }
},
"provenance": {
"cmd": ["vyges-em-ir", "run", "block.emir", "--json"],
"duration_ms": 34,
"env": {},
"maturity": "workflow-validated",
"limitations": [
"The job names the PDN or DEF/LEF and any power and decap maps; input_hash covers the job path and arguments, not their contents."
]
}
}
Fields
| Field | Always present | What it is |
|---|---|---|
schema | yes | Envelope version — loom-result/1.1. |
tool / tool_version | yes | Which engine ran, and its resolved version. |
status | yes | Execution state: ok or error. |
engineering | yes | Design verdict — see below. |
input_hash | yes | BLAKE3 over the resolved binary identity, version, declared environment, and argument vector. |
result | yes | The engine’s own --json, passed through unchanged. |
artifacts | yes (may be []) | Produced files: role, path, and a BLAKE3 hash (null if the file is declared but absent). Paths are workspace-relative where they can be (see below). Sign-off engines report the path as report_path in their own output, so asking for a report never costs you the parsed result. |
error | yes (null when fine) | Populated only when status is error. |
logs | yes (null when none) | Structured events plus a compact summary. |
provenance | yes | cmd, duration_ms, the declared env, plus the engine’s maturity and its limitations — see below. |
Parse defensively: new optional fields may appear, so ignore what you do not recognize.
The two status axes
The single most important thing about this envelope: status and engineering.status are
independent, and neither implies the other.
status | engineering.status | |
|---|---|---|
| Question | Could we invoke and observe the process? | What does the evidence support about the design? |
| Values | ok, error | pass, fail, unknown, not_applicable |
A DRC run that exits cleanly having found three violations is a successful execution of a failed check:
{ "status": "ok",
"engineering": { "status": "fail", "assertion": "drc-clean",
"summary": "3 rule violation(s) found" } }
Collapsing these into one field would force every caller to know each engine’s private JSON shape to learn whether the design actually passed — and would leave no way to say “the tool ran, but the evidence is not trustworthy.”
When the verdict is unknown
unknown is not a failure. It means no trustworthy conclusion was reached, and it is the
answer in every one of these cases:
- the engine declares no assertion — silence is never a pass;
- the execution did not succeed — a crashed, missing, or timed-out tool reached no conclusion
about the design, and reporting
failwould blame the design for a tooling defect; - the verdict field is missing, null, or the wrong type — absence of evidence is not evidence of a defect;
- the engine’s assertion is malformed and was therefore dropped;
- the engine’s maturity is
discovered— nothing has validated its result shape, so a claim from it is not yet something to rely on.
not_applicable is different again: the operation establishes no engineering claim at all — a
viewer, a format converter.
The rule to build on: treat anything other than pass as not proven, and never infer a
pass from a field you cannot interpret.
engineering.assertion names the claim (drc-clean, timing-met, …) and is null when none
was declared. Which field an engine derives its verdict from is published in its
descriptor.
Errors — structured, never a crash
Every failure mode — engine not installed, non-zero exit, unparsable output — comes back as the
same envelope with status: "error", so a session, flow, or job stays alive and can retry:
{ "status": "error",
"engineering": { "status": "unknown", "assertion": null,
"summary": "execution did not complete; no engineering conclusion reached" },
"error": { "code": "engine_nonzero", "message": "vyges-drc exited with code 2",
"exit_code": 2, "stderr_tail": "…" } }
error.code | Meaning |
|---|---|
not_installed | The engine binary is not on PATH — run vyges install <engine>. |
exec_failed | The process could not be started. |
engine_nonzero | It ran and exited non-zero; exit_code and stderr_tail are included. |
Note the pairing: an error envelope carries engineering.status: "unknown", never "fail".
input_hash — reproducibility and caching
input_hash is a BLAKE3 digest over the resolved binary identity (path or container image), the
engine version, the declared environment (PDK_ROOT and friends), and the full argument vector.
Pinning a different version, image, or PDK changes the hash.
Use it as a cache key and as a determinism check: the same input_hash must yield the same
artifacts hashes. If it does not, something outside the recorded inputs is leaking into the
result.
It covers the invocation, not the full transitive input closure — a SPICE deck’s .include
chain or a rule deck’s imports are not enumerated. In fact it does not hash file contents at
all: a job file that names a netlist contributes only its own path, so editing that netlist in
place leaves the hash unchanged. Treat it as an invocation fingerprint, not a content hash of every
byte the engine read.
Rather than leave that boundary to be rediscovered, every engine declares its own:
"provenance": {
"maturity": "workflow-validated",
"limitations": [
"The job names the floorplan and per-block power; input_hash covers the job path and arguments, not their contents."
]
}
limitations is the engine’s own statement, carried beside the hash it qualifies.
maturity says how far that engine’s evidence has been proven — and at discovered a verdict is
suppressed to unknown however well-formed the assertion. Both are declared in the
tool descriptor.
Artifact paths are workspace-relative
A path is reported relative to the working directory whenever it lies inside it:
"artifacts": [ { "role": "thermal_report", "path": "report.rpt", "hash": "blake3:…" } ]
An absolute path pins evidence to one machine and carries the host’s directory layout into a record meant to be shared, cached and compared. A path outside the workspace is left exactly as given — it has no portable form, and rewriting it would produce something that does not resolve.
The envelope is validated on the way out
Every envelope is checked against the published schema before it is returned. It is easy to validate only what arrives from elsewhere and never what leaves — the strong guarantees then apply to hypothetical third parties and the weak ones to your own evidence. This is the other way round.
A violation is our defect, not yours: it is reported as a MCP-ENVELOPE-INVALID event and the
envelope is still returned, because a caller holding a slightly wrong envelope is better off than
one holding none.
logs — the causal trail
Engines emit structured events on stderr. Those are collected here as events,
with a summary giving counts by severity and the distinct codes seen, so you get a queryable
trail plus a small handle without the full blob. logs is null when a run produced no events.
During a long run these same events stream live as MCP notifications/message, so an agent
sees progress instead of waiting for a capture-at-end dump.
Stability
loom-result/1.1 added the engineering block; 1.0 had a single status field. Additions are
backwards-compatible — parse defensively, ignore unknown fields, and treat a change to an existing
field’s meaning as a version bump.