Generate a config with AI
Don't want to write the config by hand? Paste the prompt below into an AI agent that can read your repository (Claude Code, Cursor, etc.). It will scan your code, infer your conventions, and write a complete shapelint.config.ts that matches what you already do, then run shapelint check and iterate.
Give the agent the full spec
For best results, also point the agent at the machine-readable spec: /llms.txt. The prompt below includes a condensed cheat-sheet so it works on its own, but the full spec removes any guesswork.
The prompt
Copy everything in the block below:
md
You are setting up **shapelint** for THIS repository. shapelint is a linter that
enforces code architecture/conventions; you declare rules by example. Your job:
scan the repo, infer its existing conventions, and write a complete, working
`shapelint.config.ts` at the repo root. Full spec: fetch `https://shapelint.pages.dev/llms.txt` if
available; otherwise use the cheat-sheet at the bottom of this prompt.
## Steps
1. Determine the source root (`src/` or `.`) and list the main directories
(components, ui, hooks, services, controllers, modules, schemas, lib, store, app / pages / routes, etc.).
2. For each meaningful group of files, open 3–5 representative files and detect
the DOMINANT convention actually used:
- Frontend UI components: e.g. `const X: React.FC<IProps> = () => {}`, `export default function X(props: IProps)`, or named exports
- Backend controllers & services: e.g. `@Controller('...') export class ${Name}Controller {}`, constructor DI patterns, method decorators (`@Get`, `@Post`)
- Domain models, schemas & DTOs: e.g. `export class ${Name}Dto {}`, Drizzle/Prisma schema exports, enum shapes
- Props interface/type naming (`IProps`? `XProps`?)
- File naming & folder naming (kebab-case / PascalCase / camelCase / snake_case)
- Import layering & dependency graphs (e.g. database/schemas → utils → core → features)
- Hooks (`use-*`), service patterns, route handlers
3. Write `shapelint.config.ts`. Create ONE rule per meaningful file group, with a
`pattern` that MIRRORS the dominant style you observed. Do NOT impose a style
the repo doesn't already use. Use `$Name` (PascalCase), `$name` (camelCase),
`$NAME` (CONSTANT_CASE) placeholders, a placeholder bound once must be the
same everywhere, including in `filename`.
4. Add `denyImports` / `allowImports` reflecting the REAL layering. Add
`filename` / `foldername`, and config-level `naming` for uniform conventions.
`exclude` or `ignore` framework files (Next.js `page`/`layout`/`route`,
`*.d.ts`, generated code).
5. Set `unmatched: 'ignore'` for now. Then run `npx shapelint check` and iterate
until only intentional violations remain. Report which violations are real
problems vs. rules that need loosening.
6. If there are many rules, put each in `.shapelint/rules/<name>.ts`
(`export default defineRule({...})`) and import them into the config.
## Rules of engagement
- MIRROR existing conventions; don't invent new ones.
- "The template is a lower bound": put only what MUST hold in `pattern`, leave
bodies and extra members out. Extra private declarations are fine.
- Pass `pattern` a list when a group legitimately has 2–3 shapes (e.g. plain + forwardRef).
- Minimal and correct beats exhaustive.
- At the end: show the config, explain each rule in one line, and paste the
`shapelint check` results.
## shapelint cheat-sheet
Config: `{ root, ignore, sameType, unmatched:'ignore'|'warn'|'error',
sourceFiles, output, naming, judge, rules }`.
Rule: `{ name, description, files, exclude, pattern, filename, foldername,
denyImports, allowImports, disallowElements, disallowCalls, allowExtraExports,
requires, belongsHere, semantic, hint, severity:'error'|'warn'|'off' }`.
- `pattern`: a TS snippet with `$Name`/`$name`/`$NAME` holes.
- `filename`: `'$Name.tsx'` | `'kebab-case'|'PascalCase'|'camelCase'` | `'use-*'`.
- `foldername` / `naming.files` / `naming.folders`: `kebab-case | camelCase |
PascalCase | snake_case | CONSTANT_CASE`.
- `denyImports`/`allowImports`: globs; `@/x` resolves to `x` under root; bare
packages are external. `allowImports` governs internal imports only.
- `disallowElements`/`disallowCalls`: `[{ name, useInstead, within?, except? }]`;
`*` is a wildcard; `within` is a lexical JSX ancestor.
- `allowExtraExports`: default open; `false` closes the export surface.
- `requires`: sibling files; `{stem}` = name before the first dot
(`orders.module.ts`→`orders`, `Button.tsx`→`Button`).
- `belongsHere`: `{ exportsType, importsNone }`, flags a matching file living elsewhere.
- Rules evaluate top-to-bottom; first `files` match wins.
- Config is `shapelint.config.ts` at the repo root: `import { defineConfig } from
'shapelint'; export default defineConfig({ ... })`.
Now scan the repository and produce the config.The prompt directly points the agent to https://shapelint.pages.dev/llms.txt for the full machine-readable spec.
After the agent finishes
- Review the rules. The agent mirrors what it sees, if the repo is inconsistent, tell it which style is canonical and have it regenerate.
- Run it yourself:
npx shapelint check. Fix real violations; loosen rules that are too strict. - Tighten later: once green,
npx shapelint baselineto grandfather anything legacy, then setunmatched: 'error'to close the escape hatch.
See Configuration and the Example config for the full option reference.