# Authoring Custom Diagnostics with Volar > [Docs Index](README.md) • [Repo README](../README.md) • [Plugin Authoring](plugin-authoring.md) • [Testing & CI](testing-and-ci.md) This recipe shows how to add bespoke diagnostics to Volar—enforcing naming conventions, linting custom directives, or validating config keys—while keeping behavior consistent across editors and CLI. ## Step 1: Language-Service Plugin Skeleton ```ts import type { LanguageServicePlugin } from '@volar/language-service'; export function createCustomDiagnosticsPlugin(opts: { ruleName: string }): LanguageServicePlugin { return { name: 'custom-diagnostics', capabilities: { diagnosticProvider: true }, create(context) { return { async provideDiagnostics(uri) { const doc = context.documents.get(uri); if (!doc) return []; const diagnostics = []; const text = doc.getText(); for (const match of text.matchAll(/TODO/g)) { diagnostics.push({ source: opts.ruleName, message: 'TODO found', severity: 2, range: { start: doc.positionAt(match.index!), end: doc.positionAt(match.index! + match[0].length), }, }); } return diagnostics; }, }; }, }; } ``` ## Step 2: Register in Server & CLI - Add the plugin to your language-service creation logic (see [Plugin Authoring](plugin-authoring.md)). - Ensure CLI tooling reuses the same service so diagnostics match between editor and CI. ## Step 3: Configuration Hooks Expose rule configuration via `server.configurations`: ```ts type CustomDiagConfig = { forbidTodos?: boolean; severity?: 1 | 2 | 3 | 4; }; const plugin = createCustomDiagnosticsPlugin({ ruleName: 'forbid-todo', }); ``` Reload the plugin (or pass updated options) when configuration changes. ## Step 4: Testing 1. Unit-test `provideDiagnostics` with mocked documents. 2. Run integration tests via LSP harness (`textDocument/publishDiagnostics`). 3. Execute CLI tests to verify exit codes and output formatting. ## Step 5: Workspace Diagnostics If your server uses `collectDiagnostics(document)` for workspace diagnostics, custom rules come along for free. Ensure each diagnostic has a unique `source` to help users filter. ## Tips - **Performance**: Avoid expensive operations inside diagnostics; cache ASTs where possible. - **Severity control**: Allow users to downgrade severity (`warning` vs `error`). - **Docs**: Document rule IDs and how to disable them (per-file comments, config flags). - **CLI flags**: Provide `--max-warnings` or `--rules custom.json` for automated pipelines. Following this pattern makes it easy to extend Volar’s diagnostics with project-specific rules that work everywhere your tooling runs.