Skip to content

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 baseline to grandfather anything legacy, then set unmatched: 'error' to close the escape hatch.

See Configuration and the Example config for the full option reference.

Released under the MIT License.