Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

CommandBinaryWhat it does
vygesvygesTop-level CLI: list modules, agent guide, bug/feature/sponsor
vyges pdk-storevyges-pdk-storeConsistent PDK presentation + resolution
vyges catalogvyges-catalogSearch 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 --help output.

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.0 JSONL) — the causal trail the MCP layer and vyges model consume. Filter them with VYGES_LOG and pick text vs JSONL with VYGES_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 with 2>/dev/null you 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.

FlagLevelShows on stderr
-q -q -qoffnothing (exit code still signals errors)
-q -qerrorerrors only
-qwarnerrors + warnings
(default)infoerrors + warnings + info/hints
-vdebug+ debug detail
-v -vtrace+ 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 (05) 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, then vyges 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 installedClaude 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 vyges interactively, it offers to do this for you (once). Decline and it won’t ask again; run vyges mcp setup yourself anytime. Set VYGES_NO_PROMPT=1 to 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 from vyges 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 --json output, wrapped in a loom-result envelope (status, engineering, a content-addressed input_hash, provenance). Errors come back as a structured envelope too — a bad call never crashes the session.

  • Two independent status axes. status says whether the process ran (ok | error); engineering.status says 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 is status: "ok" with engineering.status: "fail" — a successful call reporting a failed check. An engine that crashes is unknown, never fail, 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 — drc takes gds, deck, top, not an opaque string. Tools without a descriptor (and external tools like yosys) fall back to an args array of the engine’s own CLI arguments; --json is 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_PROFILEExposesUse it for
full (default)every toolunrestricted local use — unchanged behavior
coreread-only engines only (sign-off / verify / query)let an agent analyze and explain your design with no way to change it
proread-only + mutating engines behind an approving transactionagent-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 :ro for read-only.
  • entrypoint — the command inside the container (default: the tool name). Set it to "" to use the image’s own ENTRYPOINT, 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:

  1. env VYGES_MODEL_<NAME> — a JSON object (per-invocation / CI override)
  2. project ./.vyges/model.json — a repo pins its model
  3. 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 as vyges loom <engine> (e.g. vyges loom sta-si run top.sta). Each engine is also a standalone vyges-<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
EngineCommandJob fileOutput
charvyges loom char.char / .charlibLiberty .lib
extractvyges loom extract.extSPEF
powervyges loom power.pwrpower report + activity map
sta-sivyges loom sta-si.staWNS / TNS / worst path
em-irvyges loom em-ir.emirIR-drop map + EM check
thermalvyges loom thermal.thermaltemperature field + hotspot
lvsvyges loom lvs.lvsMATCH / MISMATCH + diagnostics

Optimizers — they read the timer’s verdict and edit the netlist to fix it:

EngineCommandJob fileOutput
resizevyges loom resize.resizeresized netlist (drive sizing)
vt-swapvyges loom vt-swap.vtswapresized netlist (Vt / leakage)
buffer-insertvyges loom buffer-insert.bufinsbuffered netlist (transition fix)

Verification + utilities — prove correctness, or view the layout:

EngineCommandInputOutput
drcvyges loom drcGDS + .drc deckgeometry violations
cdcvyges loom cdcnetlist + lib + SDCclock-domain crossings
glitchvyges loom glitchnetlist + Libertyreconvergent-fanout hazards
lecvyges loom lectwo netlists + libEQUIVALENT / NOT + counter-ex.
gds-viewvyges loom gds-viewGDS (+ 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 run vyges loom char. It’s also a standalone vyges-char binary 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

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 run vyges loom extract. It’s also a standalone vyges-extract binary 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

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 run vyges loom power. It’s also a standalone vyges-power binary 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

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 run vyges loom sta-si. It’s also a standalone vyges-sta-si binary 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

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 run vyges loom em-ir. It’s also a standalone vyges-em-ir binary 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

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 run vyges loom thermal. It’s also a standalone vyges-thermal binary 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 run vyges loom lvs. It’s also a standalone vyges-lvs binary 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

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 run vyges loom resize. It’s also a standalone vyges-resize binary 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

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 run vyges loom vt-swap. It’s also a standalone vyges-vt-swap binary 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

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 run vyges loom buffer-insert. It’s also a standalone vyges-buffer-insert binary 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

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 run vyges loom hold-fix. It’s also a standalone vyges-hold-fix binary 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

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 run vyges loom drc. It’s also a standalone vyges-drc binary 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 run vyges loom cdc. It’s also a standalone vyges-cdc binary 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 run vyges loom glitch. It’s also a standalone vyges-glitch binary 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 run vyges loom lec. It’s also a standalone vyges-lec binary 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 run vyges loom gds-view. It’s also a standalone vyges-gds-view binary 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 run vyges loom meas. It’s also a standalone vyges-meas binary 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

choicethis kernel
record lengthpower of two, 8 to 65,536 samples
samplingcoherent — the fundamental lands exactly on a DFT bin, and you say which
windownone. A rectangular window is exact for a coherent capture and wrong otherwise, so a non-coherent capture is refused, not smeared
DCthe mean is removed and the DC bin is excluded from every partition
harmonicsfolded into the first Nyquist zone — an aliased harmonic’s power is really in the record
integration widthzero bins: each component is exactly one bin, never a skirt
collisionsa harmonic landing on DC, the fundamental, or another harmonic is refused — counting one bin twice would double-count its power
clippinga 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:

levelmeans
vyges-definitionthe method is ours, complete and versioned. No external standard is claimed.
candidatethe application lies inside a named standard’s published scope, but no clause-level review has been done
revieweda crosswalk records the exact edition, clauses, choices, deviations, reviewer and artifact
conformantan 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:

--applicationreachesagainst
generic (default)vyges-definition
adccandidateIEEE 1241-2023
daccandidateIEEE 1658-2023
recordercandidateIEEE 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 run vyges loom remap. It’s also a standalone vyges-remap binary 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:

equivalentwhen
truethe check ran and the mapped netlist is equivalent
falsethe check ran and it is not — the remap is rejected
nullthe 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-layout is 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 a vyges loom subcommand (it’s an internal foundation, used as a standalone vyges-layout binary). 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

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-events is the shared structured-event and logging contract that every Loom engine emits — and the substrate the MCP layer and cross-stage analysis consume. Like vyges-layout it’s a foundation crate, not a promoted vyges loom subcommand.

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:

VariableEffect
VYGES_LOG=<level>severity filter — trace|debug|info|warn|error (default info)
VYGES_LOG_FORMAT=json|textforce 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

FieldMeaning
schemaalways vyges-events/1.0
ts_msunix epoch milliseconds
toolemitting engine (vyges-drc, vyges-lvs, …)
severitytrace/debug/info/warn/error
codestructured code (DRC-WIDTH, LVS-MISMATCH, …) — the clustering key
objectsdesign objects named (net:data[3], cell:sram0, layer:66) — the cross-stage co-reference key
raw_msg / msg_templatethe message (full / with variable parts masked)
run_id / step_index / stageorchestration context (stamped by the runner)
filesource 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 the loom-result envelope’s logs block (a compact summary — counts by severity, the codes seen — plus the events), and streams each line live as an MCP notifications/message while a long tool call runs, so you see progress instead of a capture-at-end blob.
  • A vyges model run 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 its run_id and step_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:

FormatEngineDeclares
.char / .charlibvyges-charcorner(s), cells, SPICE collateral
.extvyges-extractdesign, PDK parasitic rules, settings
.pwrvyges-powernetlist, libraries, activity source, budget
.stavyges-sta-silibraries, parasitics, constraints
.emirvyges-em-irdesign, PDN, IR/EM budget
.thermalvyges-thermaldie + grid + material params, floorplan, limit
.lvsvyges-lvslayout (GDS) + schematic netlist

Optimizers · act — netlist in, better netlist out (each move scored by sta-si):

FormatEngineDeclares
.resizevyges-resizenetlist, libraries, (SPEF), timing / area goal
.vtswapvyges-vt-swapnetlist, libraries, (SPEF), leakage / timing goal
.bufinsvyges-buffer-insertnetlist, 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:

EngineFlow stageSits beside (OSS)Adds
vyges-charcell characterization (upstream)Liberatea .lib when you don’t already have one
vyges-extractparasitic extraction (post-route)OpenRCXcoupling-aware SPEF (the SI input)
vyges-powerpower analysis (post-synth / post-route)OpenSTA report_powerleakage + dynamic, and the activity map em-ir needs
vyges-sta-sistatic timing (signoff)OpenSTASI/crosstalk + statistical (AOCV/POCV-LVF) OCV
vyges-em-irpower integrity (PDN)PDNSimIR-drop / EM second opinion
vyges-lvslayout-vs-schematic (signoff)NetgenMATCH/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.

EngineRuns onCatches early
vyges-sta-sisynth netlist + .lib + SDCbroken constraints, a timing wall, bad clock setup
vyges-powersynth netlist + .lib + VCD/vectorlessa 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.

EngineRuns onRole
vyges-extractrouted DEFSPEF — second opinion vs OpenRCX (0.997 on a routed block)
vyges-sta-sinetlist + real SPEFpost-route timing with the actual parasitics
vyges-em-irPDN + currentsIR-drop / electromigration
vyges-lvsextracted GDS + schematicMATCH / 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

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/ and integrations/ — 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, --help is 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

FieldRequiredWhat it is
nameyesStable tool id (drc, sta-si, …). The MCP tool takes this name.
summaryyesOne line, shown as the tool’s description.
invocationyesHow to build the command — see below.
inputsnoJSON Schema for the callable parameters. Defaults to an empty object schema.
artifactsnoThe files the run produces, and how to locate them.
assertionnoHow to derive the engineering verdict. Omitted → the result is unknown.
maturitynoHow far the evidence has been proven. Omitted → discovered, which suppresses the verdict.
provenance_limitationsyesWhat input_hash does not cover, in the engine’s own words.
consumesnoInput 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 for name. Tokens are required: a missing one is a caller error, not a default.
  • optional — appended only when supplied. With flag, the pair --top TOP is appended; without one, the bare value is appended.
  • emits_json — when true (the default), callers append --json if 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).

KeyMeaning
roleWhat the file isdrc_report, timing_report, lvs_report, netlist, svg, …
fieldKey in the engine’s --json output holding the path.
from_argInput-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_whenPasses 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 null in those cases rather than forcing a boolean; null resolves to unknown, 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.

LevelMeans
discoveredThe binary resolves and reports a version. Nothing about its output is guaranteed.
structuredIt publishes a versioned operation and a normalized result — a descriptor like this one.
workflow-validatedIts 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 reportedengineering.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.

LevelEngines
workflow-validatedsta-si · em-ir · lvs · extract · thermal · power
structureddrc · 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 vectornot 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 --json payload. The envelope is added by the layer that runs them, and the engine’s own output is carried inside it verbatim as result.

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

FieldAlways presentWhat it is
schemayesEnvelope version — loom-result/1.1.
tool / tool_versionyesWhich engine ran, and its resolved version.
statusyesExecution state: ok or error.
engineeringyesDesign verdict — see below.
input_hashyesBLAKE3 over the resolved binary identity, version, declared environment, and argument vector.
resultyesThe engine’s own --json, passed through unchanged.
artifactsyes (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.
erroryes (null when fine)Populated only when status is error.
logsyes (null when none)Structured events plus a compact summary.
provenanceyescmd, 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.

statusengineering.status
QuestionCould we invoke and observe the process?What does the evidence support about the design?
Valuesok, errorpass, 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 fail would 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.codeMeaning
not_installedThe engine binary is not on PATH — run vyges install <engine>.
exec_failedThe process could not be started.
engine_nonzeroIt 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.