Skip to Content
DocsIntegrationsEditor support

Editor support

Hand-authored YAML flows get autocomplete, hover docs, and inline validation in any editor that speaks JSON Schema. There is no klera-specific editor extension — the schema is exported, the editor reads it, you type.

Export the schema

klera schema --out .klera/flow.schema.json --pretty

The schema is derived from the same Zod IR the parser uses, so anything the runtime accepts the editor knows about — and anything the editor flags is something the parser would reject at run time.

Flags:

  • --out <path> — where to write the schema. Without it, prints to stdout.
  • --pretty — pretty-print the JSON (recommended for committed files; diffs stay readable).

klera init runs this automatically as part of the scaffold and points the YAML schema directive at it.

Wire it up in your YAML

Add the # yaml-language-server comment at the top of every flow file:

# yaml-language-server: $schema=../.klera/flow.schema.json name: Login smoke steps: - tap: Sign In - type: { into: email, value: pm@example.com } - tap: Continue - assert: { visible: Welcome back }

klera init adds the directive automatically when it scaffolds the YAML opt-in (init --yaml). Existing flows just need the one-line header.

The path is relative to the flow file. For nested layouts (flows/auth/login.flow.yaml), bump the .. count to reach the schema:

# yaml-language-server: $schema=../../.klera/flow.schema.json

What you get for free

Any editor with a JSON Schema-aware YAML extension picks up the schema without extra config:

EditorProvider
VS Coderedhat.vscode-yaml
JetBrainsBuilt-in YAML support (IntelliJ, WebStorm, RubyMine, …)
Neovimyamlls via nvim-lspconfig
HelixBuilt-in YAML LSP
SublimeLSP + LSP-yaml

All of them deliver the same three things: completions, hover docs, inline validation.

Completions

Type - and the editor offers every step keyword. Type tap: and you get the target-spec fields. Type target: and you get testID / text / accessibilityLabel / role / scope.

steps: - # cursor here # ↓ completion popup # tap # type # assert # waitForIdle # visualSnapshot # swipe # scroll # …

Hover docs

Hover any keyword to see its description from the Zod schema — including value constraints (role is one of button | link | …, durationMs is a positive integer).

Inline validation

Misspelled keys, wrong types, missing required fields, and unknown variants are flagged before you save.

steps: - tap: testid: login-submit # ↑ Property "testid" is not allowed. Did you mean "testID"? - type: into: { testID: login-email } # missing: value (required)

The schema is strict — every Step variant uses Zod’s .strict(), so multi-keyword steps like { tap: …, type: … } are flagged as “Unrecognized key” instead of silently parsing as the first variant. This is the same gate the parser applies; the editor is just surfacing it earlier.

Schema-as-code

The schema is derived from the Zod IR via zod-to-json-schema, so it follows the IR in lockstep:

  • Add a new step variant to @klera/protocol → bump → re-run klera schema → editors see it.
  • Tighten an existing field’s type → same flow.

There is no second source of truth and no hand-maintained schema file in the repo. Editor validation matches runtime validation.

Refreshing the schema

Bump @klera/cli (or @klera/protocol), then re-run:

klera schema --out .klera/flow.schema.json --pretty

Commit the regenerated file. Reviewers see the schema diff alongside the version bump — useful context when a release adds a new step.

CI can gate on schema freshness the same way it gates on prose-cache freshness. A klera schema --out /tmp/check.json --pretty && diff .klera/flow.schema.json /tmp/check.json step fails the build if someone bumped klera but forgot to regenerate.

See also

  • Planner transports — for prose flows the LLM produces the IR and the cache; the schema applies to the YAML escape hatch and to anything you author by hand.
Last updated on