Lint generated proxies
Generated proxy files live inside your source tree, next to the commands and queries they came from — which means your ESLint config sees them too, unless you tell it not to.
Lint with your application policy
Section titled “Lint with your application policy”The C# generator emits a standard license header, followed by the unchanged // @generated by Cratis metadata format. Fourth-line recognition requires the standard Cratis copyright line, license line, and blank third line; a marker inside an authored multiline template literal does not qualify. Older first-line markers remain recognized. Generated output contains no blanket ESLint disable directives or @ts-ignore comments, so you can keep unused-disable reporting at error, including with a minimal TypeScript parser configuration that has no rule plugins.
If you lint generated files, your consumer configuration must permit their existing exported empty interfaces, including interfaces with inherited members but no own members. These are supported public shapes: they preserve declaration merging and existing assignability. Configure the applicable @typescript-eslint/no-empty-interface and @typescript-eslint/no-empty-object-type policies accordingly. This is a target-language contract, not an unused-directive waiver; keep reportUnusedDisableDirectives at error.
Application checks such as license headers, named import-member sorting, and TypeScript-comment bans can remain active. Import members are sorted without reordering imported modules. Generated response hooks supply their response generic rather than suppressing a type error. Output is not promised to pass arbitrary library-style configurations that prohibit a supported public interface shape. Other application-specific restrictions may still need consumer configuration; for example, React hook rules can flag the generated static .use() methods as hook calls inside a class.
If you prefer not to lint generated files at all, use the opt-in processor below. It does not relax checks on your hand-written source.
Skip generated files
Section titled “Skip generated files”A generated .ts file carries a // @generated by Cratis header and a **DO NOT EDIT** banner, and the proxy generator rewrites it whenever a build regenerates its contract (by default Arc skips files whose generated content is unchanged). Generation follows CratisProxiesOutputPath, not the build configuration, so a Release build with that path set regenerates too. Any lint finding on that file is unactionable: you cannot fix it by hand without the fix being discarded on the next build, and you cannot fix the generator’s output style through your project’s lint rules. Left unconfigured, a project either accumulates lint noise it can never resolve, or hand-maintains a path allow-list that has to be kept in sync with every new command and query folder.
Configure the skip processor
Section titled “Configure the skip processor”@cratis/eslint-plugin-arc ships a skip-generated-proxies processor that detects the // @generated by Cratis header and skips the file wholesale. Because it keys on the header rather than a path pattern, it works regardless of where a proxy sits — intermixed with hand-written .ts/.tsx files in the same slice folder, a layout many projects choose by pointing CratisProxiesOutputPath at their source root — with no allow-list to maintain.
Install
Section titled “Install”yarn add -D @cratis/eslint-plugin-arc @cratis/eslint-config eslintimport cratis from '@cratis/eslint-config';import arc from '@cratis/eslint-plugin-arc';
export default [ ...cratis.configs.consumer, ...arc.configs.recommended, // …your project rules];With arc.configs.recommended composed in, a proxy file is never linted — not even for formatting — so nothing about it shows up as a finding to triage.
Other rules in the plugin
Section titled “Other rules in the plugin”The plugin also ships two rules that are not about generated files, but are worth enabling alongside the processor if you use MVVM view models or MobX:
| Rule | What it does |
|---|---|
no-hooks-in-view-model | Disallows React hook calls inside MVVM view models (classes named *ViewModel). A view model must be a plain, React-free class — inject a Cratis abstraction instead of calling a hook. |
no-direct-mobx-react-import | Disallows importing directly from mobx-react/mobx-react-lite. The MobX binding is an internal detail of @cratis/arc.react.mvvm, which re-exports observer — import it from there so the binding can evolve without breaking consumers. |
no-hooks-in-view-model takes options to fit a project’s own naming conventions:
'@cratis/arc/no-hooks-in-view-model': ['error', { classSuffix: 'ViewModel', // class-name suffix that marks a view model hookPattern: '^use[A-Z]', // bare-identifier calls treated as hooks additionalHooks: ['injectQuery'], // extra call names to forbid}]Only bare-identifier calls (useState(...)) are flagged — a member call like this.useDefaults() is not, so a view-model method that merely starts with use is safe.
See also
Section titled “See also”- File Index Tracking — the
// @generated by Cratisheader this processor keys on, and whyindex.tsdeliberately does not carry it.