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.
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:
vize lint src
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.
vize lint --preset essential src
vize lint --preset opinionated --help-level short src
vize lint --format json --max-warnings 0 src
Opt into cross-file and type-aware checks only after the basic lint path is stable:
vize lint --cross-file src
vize lint --cross-file --cross-file-tree src
vize lint --strict-reactivity src
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.
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 |
Cross-File Analyzer
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.
vize lint --cross-file src
vize lint --cross-file --cross-file-tree src
The lower-level analyzer is broader than the current CLI surface:
| Analyzer 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.
vize check
vize check src
vize check --tsconfig tsconfig.app.json
vize check --format json --quiet
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.
vize check --show-virtual-ts src/components/App.vue
vize check --profile src
vize check --servers 1 src
Declaration output is available from the materialized checker project:
vize check --declaration --declaration-dir dist/types
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 };
}
}
vize check --tsconfig tsconfig.app.json
npm CLI vs Rust CLI
The npm vize package is intended for package scripts and uses the packaged NAPI binding:
vp exec vize lint src
vp exec vize check src --strict
vp exec vize ready src
The Rust CLI currently has the fuller project-backed type-checking surface:
nix run github:ubugeeei/vize#vize -- check --tsconfig tsconfig.app.json --profile src
vize check --tsconfig tsconfig.app.json --profile src
vize lsp
Use the npm CLI when you want installable scripts 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
vize lint --preset essential srcto CI.Switch to
happy-pathoropinionatedafter correctness diagnostics are clean.Add
vize checkwith 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, vize ready src runs fmt --write, lint, check, and build in
order and stops at the first failing step.