How `native check` Performs Markup Validation and Reports File:Line:Column Errors in Native SDK Apps

native check scans the src/ directory for .native markup files, validates them via markup_cli.checkFiles, and emits precise file:line:column diagnostics that let developers jump straight to the source of any error—without ever building the app.

As implemented in vercel-labs/native, the native check command provides fast, build-free validation for Native SDK applications. Its markup validation pipeline checks TypeScript cores, .native files, and the app.zon manifest while surfacing every issue with exact file, line, and column coordinates.

The native check Markup Validation Pipeline

In tools/native-sdk/main.zig, the native check entry point orchestrates a six-stage pipeline that validates the whole app without producing a build.

Locate the App Manifest

First, native check looks for an app.zon file in the current directory—or the directory you pass—to confirm it is inside a Native SDK app. If the file is missing, the command aborts immediately with a MissingManifest error.

Run the TypeScript Core Checker

If the app uses a TypeScript core, native check runs the @native-sdk/core subset checker before any markup validation. This ensures TypeScript diagnostics are collected and reported alongside markup issues.

Collect Markup Files

The command invokes collectMarkupFiles, defined in tools/native-sdk/markup.zig, to recursively walk src/ and gather every file whose extension matches a markup file—specifically .native. The function returns a list of absolute paths that are fed into the validator.

Validate Markup Files

The collected paths are passed to markup_cli.checkFiles. The validator returns a CheckOutcome structure containing the count of failures, warnings, and whether the model-contract was checked. This stage is where markup syntax and semantics are evaluated against the app's contract.

Validate the Manifest

After markup checks, app.zon is parsed and validated using tooling.manifest.validateFile from src/tooling/manifest.zig. Any manifest problems are printed, and if validation fails, the command exits with an error.

Report Results and Strict Mode

Finally, native check prints a one-line summary such as:

checked 3 markup files against the model contract, app.zon

If you pass the --strict flag, warnings are promoted to errors, causing the command to fail even when only warnings are present.

File:Line:Column Error Format in Markup Diagnostics

When the markup compiler finds a problem, it prints diagnostics in a file:line:column format that editors and terminals can parse directly. According to the vercel-labs/native README:

"native check validates every view … with file:line:column errors that teach."

The underlying diagnostics are generated by src/primitives/canvas/ui_markup.zig. Inside the markup compiler, the printDiagnostic logic attaches source locations to each node and formats them as file:line:column when emitting errors.

A typical CLI output looks like this:


# Example error output

src/app.native:12:5: unknown tag "buttonn" (did you mean "button"?)

This pinpoint output eliminates guesswork and allows IDEs to jump directly to the offending line and column.

Running native check from the Command Line

You invoke the validator from inside an app directory. The following examples show the standard and strict modes:


# Validate TS core, markup, and app.zon

native check

# Promote warnings to errors

native check --strict

Because validation runs without a build step, the feedback loop is nearly instantaneous.

Key Source Files Behind native check

Understanding the architecture is easier when you know which files handle each responsibility:

  • tools/native-sdk/main.zig — The CLI entry point that orchestrates the core checker, markup validation, and manifest verification.
  • tools/native-sdk/markup.zig — Implements collectMarkupFiles and the CheckOutcome structure; invokes the markup validator via checkFiles.
  • src/primitives/canvas/ui_markup.zig — The markup compiler that parses .native files and emits diagnostics with file:line:column source locations through printDiagnostic.
  • src/tooling/manifest.zig — Parses and validates app.zon, providing manifest-level diagnostics.

Summary

  • native check validates an entire Native SDK app without building it.
  • The pipeline runs the TS core checker, collects .native files from src/, validates markup via markup_cli.checkFiles, and verifies app.zon through tooling.manifest.validateFile.
  • Failures and warnings are aggregated in a CheckOutcome, and results are summarized on the command line.
  • Diagnostics use a precise file:line:column format generated by src/primitives/canvas/ui_markup.zig, enabling direct navigation to errors.
  • The --strict flag elevates warnings to errors for more stringent CI/CD gates.

Frequently Asked Questions

What does native check validate besides markup?

native check validates three layers: the TypeScript core (if the app uses one), every .native markup file under src/, and the app.zon manifest. Any failure in these layers causes the command to exit with an error.

How does native check locate markup files to validate?

It calls collectMarkupFiles in tools/native-sdk/markup.zig, which recursively walks src/ and selects every file with a .native extension. These absolute paths are then passed to the markup validator.

What happens when --strict is passed to native check?

When --strict is used, all warnings collected in the CheckOutcome are promoted to errors. This guarantees that even minor markup or manifest issues will fail the command, which is useful for enforcing quality gates in continuous integration.

Where are the file:line:column diagnostics generated?

The diagnostics are generated inside src/primitives/canvas/ui_markup.zig by the markup compiler. Its printDiagnostic logic maps each AST node back to its source location and formats the output as file:line:column so that editors and terminals can resolve the exact point of failure.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →