Static Analysis
Vize's analysis stack is shared by the compiler, linter, type checker, editor server, and Musea tooling. The goal is to parse a Vue SFC once, keep rich semantic information around, and reuse it for diagnostics and code generation instead of treating each command as a separate tool.
The examples below assume the vize npm package is installed and called from project scripts, which
is the recommended workflow for applications.
Pipeline
| Layer | What it does | Used by |
|---|---|---|
| Armature | Tokenizes and parses Vue templates and SFC structure | compiler, linter, formatter |
| Croquis | Builds scopes, binding metadata, macro information, and cross-file graphs | compiler, lint, type-aware checks |
| Patina | Runs Vue, script, CSS, a11y, SSR, Vapor, Musea, and type-aware lint rules | vize lint, editor diagnostics, Oxlint bridge |
| Canon | Generates virtual TypeScript and maps diagnostics back to Vue files | vize check, editor type checking |
| Maestro | Exposes diagnostics and editor features through LSP | vize lsp, VS Code, Zed |
This means static analysis is not only linting. Template bindings, compiler macros, component metadata, provide/inject relationships, reactivity flow, generated virtual TypeScript, and component gallery metadata all depend on the same lower-level analysis work.
For the concrete rule names, defaults, and cross-file diagnostic codes that can be emitted, see Rules.
Linting
Start with the default preset:
{
"scripts": {
"vize:lint": "vize lint src"
}
}
vp run vize:lint
Use essential for correctness-only CI, happy-path for the default recommended bundle,
opinionated when you want stronger conventions, nuxt for Nuxt-aware assumptions, and
incremental when you only want explicitly configured rules to run.
{
"scripts": {
"vize:lint:ci": "vize lint --preset essential --max-warnings 0 src",
"vize:lint:opinionated": "vize lint --preset opinionated --help-level short src",
"vize:lint:fix": "vize lint --fix src",
"vize:lint:json": "vize lint --format json src"
}
}
vp run vize:lint:ci
vp run vize:lint:opinionated
vp run vize:lint:fix
vp run vize:lint:json
Opt into cross-file and type-aware checks only after the basic lint path is stable:
{
"scripts": {
"vize:lint:cross-file": "vize lint --cross-file src",
"vize:lint:cross-file-tree": "vize lint --cross-file --cross-file-tree src",
"vize:lint:strict-reactivity": "vize lint --strict-reactivity src"
}
}
vp run vize:lint:cross-file
vp run vize:lint:cross-file-tree
vp run vize:lint:strict-reactivity
Cross-file linting analyzes relationships such as provide/inject and reactivity flow across a set of
Vue files. --strict-reactivity enables the native checker-backed reactivity-loss rule, so expect it
to be slower than ordinary template and script lint rules.
Reactivity Overlay
Croquis exposes a stable reactivity overlay for each analyzed SFC: reactive sources, .value
requirements, reactivity-loss sites, and effect-graph edges with source mappings. The same compact
JSON model feeds diagnostics, reports, editor surfaces, and the Playground's Reactivity tab.
Patina Rule Model
Patina is the lint rule layer. Rules are small visitors over the SFC source, template root,
template elements, directives, v-for, v-if, and interpolations. Each rule carries metadata for
its rule name, category, default severity, help text, and whether it is fixable. Presets are just
registries that decide which rules are enabled together.
| Area | Example rules | What they cover |
|---|---|---|
| Vue correctness | vue/require-v-for-key, vue/valid-v-model, vue/no-use-v-if-with-v-for |
Template semantics that are local to one component |
| Vue security | vue/no-v-html, vue/no-unsafe-url |
XSS-prone HTML and URL sinks |
| Vue structure | vue/sfc-element-order, vue/require-scoped-style, vue/no-unused-components |
SFC shape, component usage, and maintainability |
| Script conventions | script/no-options-api, script/no-get-current-instance, script/prefer-import-from-vue |
Vue Composition API and compiler macro conventions |
| CSS | css/no-important, css/no-hardcoded-values, css/prefer-logical-properties |
Style blocks and design-system friendly CSS |
| Accessibility | a11y/img-alt, a11y/anchor-has-content, a11y/label-has-for |
Accessible markup and interaction patterns |
| HTML | html/deprecated-element, html/id-duplication, html/no-empty-palpable-content |
HTML validity and semantic markup |
| SSR | ssr/no-browser-globals-in-ssr, ssr/no-hydration-mismatch |
Server/client rendering hazards |
| Vapor | vapor/no-vue-lifecycle-events, vapor/no-inline-template, vapor/require-vapor-attribute |
Vapor-oriented template constraints |
| Musea | musea/require-title, musea/valid-variant, musea/prefer-design-tokens |
Component gallery and variant authoring |
| Type-aware analysis | type/require-typed-props, type/require-typed-emits, type/no-reactivity-loss |
Rules that need semantic or checker-backed context |
The built-in presets are meant to support adoption in stages:
| Preset | Shape |
|---|---|
essential |
Error-focused Vue correctness, security, and minimal HTML checks |
happy-path |
Default bundle for correctness, security, a11y, SSR, semantic checks |
opinionated |
happy-path plus stronger conventions, script rules, and type rules |
nuxt |
Opinionated rules adjusted for Nuxt auto-import assumptions |
incremental |
Empty starting point for host-driven, rule-by-rule adoption |
Migration Pragmas and Custom Rules
Patina accepts existing ESLint disable pragmas for matching rule names, including
eslint-disable, eslint-enable, eslint-disable-next-line, and eslint-disable-line. This lets
projects migrate rules such as vue/require-v-for-key without rewriting every suppression comment
up front.
Project-local JavaScript rule modules are not a stable Vize runtime API yet. During migration, keep
those rules in ESLint or Oxlint and run them beside vize lint, or use the incremental preset to
enable only built-in Vize rules that already match your policy. The rules config object controls
built-in Vize rule severities by name.
For the common case of forbidding a runtime-environment global (typical sidecar ESLint rules such as
no-access-process, no-access-local-storage, or no-restricted-globals against localStorage /
sessionStorage), enable the opt-in built-in script/no-restricted-globals rule instead of keeping
ESLint installed for those alone. Its default deny list is process, localStorage, and
sessionStorage, reported on each bare reference.
Two script rules also accept project-local configuration under linter.ruleOptions (#1891), so teams
can enforce their own architecture conventions through vize lint. script/no-restricted-globals
takes a globals list that replaces the built-in default list; script/no-restricted-members is
off until configured and flags <object>.<property> accesses from a members list. Options are typed
(name / object / property plus an optional message, with unknown keys rejected); a missing
message falls back to a generic advisory.
{
"linter": {
"rules": {
"script/no-restricted-globals": "error",
"script/no-restricted-members": "error"
},
"ruleOptions": {
"script/no-restricted-globals": {
"globals": [
{ "name": "process", "message": "Read env via a typed helper." },
{ "name": "alert" }
]
},
"script/no-restricted-members": {
"members": [
{ "object": "window", "property": "localStorage", "message": "Use authStorage." }
]
}
}
}
}
Cross-File Rules
Cross-file analysis lives in Croquis and is exposed to linting through Patina diagnostics. It is opt-in because it builds a module registry, import graph, component-usage graph, and additional indexes across all analyzed Vue files.
Today, vize lint --cross-file enables provide/inject matching, unique element ID checks,
reactivity tracking, and async race-condition analysis. --cross-file-tree prints the
provide/inject tree on top of those diagnostics.
vp run vize:lint:cross-file
vp run vize:lint:cross-file-tree
The lower-level cross-file engine is broader than the current CLI surface:
| Cross-file option | Intended diagnostics or facts |
|---|---|
provide_inject |
Unmatched injects, unused provides, string-key warnings, non-reactive flows |
unique_ids |
Duplicate IDs and non-unique IDs introduced inside loops |
reactivity_tracking |
Prop destructuring, aliasing, and cross-component reactivity loss |
race_conditions |
Async state updates that can race through provided or shared state |
fallthrough_attrs |
$attrs, inheritAttrs, and multi-root fallthrough hazards |
component_emits |
Undeclared emits, unused emits, and listeners without a producer |
event_bubbling |
Events that bubble through component boundaries without being handled |
server_client_boundary |
Browser API usage and hydration risks around SSR/client boundaries |
error_suspense_boundary |
Async components without useful Suspense or error boundaries |
circular_dependencies |
Import cycles and deep import chains |
component_resolution |
Unregistered or unresolved component usage |
props_validation |
Missing required props and child prop type mismatches |
The direction is to keep single-file linting fast by default, expose cross-file groups explicitly as they mature, and route high-confidence project facts into the same diagnostic stream used by the CLI, Oxlint bridge, and editor server.
Type Checking
vize check generates virtual TypeScript for Vue SFCs and asks Corsa project sessions for
diagnostics. It checks .vue, .ts, .tsx, and .d.ts inputs and maps diagnostics back to the
original source files.
{
"scripts": {
"vize:check": "vize check",
"vize:check:src": "vize check src",
"vize:check:app": "vize check --tsconfig tsconfig.app.json",
"vize:check:json": "vize check --format json --quiet",
"vize:check:virtual-ts": "vize check --show-virtual-ts src/components/App.vue",
"vize:check:profile": "vize check --profile src",
"vize:check:single-server": "vize check --servers 1 src",
"vize:check:declarations": "vize check --declaration --declaration-dir dist/types"
}
}
vp run vize:check
vp run vize:check:src
vp run vize:check:app
vp run vize:check:json
When no paths are provided, vize check reads tsconfig.json files, include, and exclude
fields if a project config is available. Use --show-virtual-ts when debugging generated code and
--profile when you need timing and virtual-file artifacts under node_modules/.vize.
vp run vize:check:virtual-ts
vp run vize:check:profile
vp run vize:check:single-server
Declaration output is available from the materialized checker project:
vp run vize:check:declarations
Project-wide template values and generated declaration files should be visible through TypeScript
project configuration. Put ambient declarations under a path included by your tsconfig and pass
that project file to the checker when needed:
{
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/*.d.ts"]
}
// src/types/vue-app.d.ts
declare module "vue" {
interface ComponentCustomProperties {
$t: (key: string) => string;
$route: { path: string };
}
}
vp run vize:check:app
npm Package Scripts vs Rust CLI
The npm vize package is intended for package scripts and uses the packaged NAPI binding:
{
"scripts": {
"vize:lint": "vize lint src",
"vize:check": "vize check src --strict",
"vize:ready": "vize ready src"
}
}
vp run vize:lint
vp run vize:check
vp run vize:ready
The Rust CLI currently has the fuller project-backed type-checking surface:
nix run github:ubugeeei-prod/vize#vize -- check --tsconfig tsconfig.app.json --profile src
vize check --tsconfig tsconfig.app.json --profile src
vize lsp
Use npm package scripts when you want installable workflows in an application. Use the Rust CLI when
you need check-server, LSP, IDE management, or the Corsa-backed project diagnostics path across
Vue and TypeScript files.
Oxlint
Use oxlint-plugin-vize when your team already runs Oxlint and wants Vue-aware diagnostics in the
same command:
vp install -D oxlint oxlint-plugin-vize
vp exec oxlint-vize -c .oxlintrc.json -f stylish src
{
"plugins": ["vue"],
"jsPlugins": ["oxlint-plugin-vize"],
"settings": {
"vize": {
"preset": "essential",
"helpLevel": "short"
}
},
"rules": {
"eqeqeq": "error",
"vize/vue/require-v-for-key": "error",
"vize/vue/no-v-html": "warn"
}
}
Adoption Path
Add a
vize:lint:cipackage script such asvize lint --preset essential srcto CI.Switch to
happy-pathoropinionatedafter correctness diagnostics are clean.Add a
vize:checkpackage script with your projecttsconfig.json.Enable editor linting first, then type checking once CI output is stable.
Add cross-file and strict reactivity checks for projects that benefit from deeper analysis.
For a single quality gate, a vize:ready package script running vize ready src runs fmt
--write, lint, check, and build in order and stops at the first failing step.