npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@alexgorbatchev/typescript-ai-policy

v12.0.1

Published

Shared TypeScript AI policy configs and Oxlint rules

Readme

@alexgorbatchev/typescript-ai-policy

Shared Oxfmt and Oxlint config for teams that want AI-assisted TypeScript to stay strict, predictable, and reviewable.

This package is opinionated on purpose. It does not try to be a flexible style preset. It encodes repository contracts as lint rules so generated and modified code lands in a shape you can actually trust.

Who this is for

Use this package if you want to:

  • enforce stricter structure on AI-generated or AI-modified TypeScript
  • replace hand-wavy coding guidance with machine-checkable rules
  • keep React, tests, fixtures, and type boundaries deterministic
  • ship one shared policy pack across repositories

If you want a loose collection of optional style rules, this package is the wrong tool.

What you get

  • shared Oxfmt config
  • shared Oxlint config
  • custom @alexgorbatchev/* rules aimed at common LLM failure modes
  • diagnostics written as direct repair instructions
  • the typescript-ai-policy CLI with fix-semantic and guidance commands

Upstream Oxlint, TypeScript, and Jest rules stay enabled as baseline correctness guardrails.

Install

bun add -d @alexgorbatchev/typescript-ai-policy oxfmt oxlint

If you want to use the typescript-ai-policy fix-semantic command, install its optional peer dependencies:

  • If your project is already using TypeScript 7+:
    bun add -d typescript
  • If your project is on TypeScript 6 (you must also install the native preview LSP backend for the fixer to run):
    bun add -d typescript @typescript/native-preview

The published package ships compiled .js runtime files plus .d.ts declarations. The installed typescript-ai-policy CLI runs through Bun, so Bun is required to execute the package-installed bin. The fix-semantic command still expects its optional peer dependencies to be installed in the consuming project, while guidance only reads the published policy metadata.

Quick start

oxfmt.config.ts

import createOxfmtConfig from "@alexgorbatchev/typescript-ai-policy/oxfmt-config";

export default createOxfmtConfig(() => ({
  ignorePatterns: ["vendor/**"],
}));

oxlint.config.ts

import createOxlintConfig from "@alexgorbatchev/typescript-ai-policy/oxlint-config";

export default createOxlintConfig({
  ignorePatterns: ["coverage"],
  rules: {
    "no-var": "error",
  },
});

Both config entrypoints export factory functions. createOxlintConfig(...) accepts either a config object or a callback that returns one. The returned user config is deep-merged before the shared defaults, so the shared policy still wins on conflicting keys.

For Oxlint specifically, consumer configs are extension-only. If the provided config tries to redefine a shared rule, the factory throws instead of letting repositories silently weaken the policy downstream.

createOxlintConfig also exports FilenameStyle as a named export from @alexgorbatchev/typescript-ai-policy/oxlint-config. createOxlintConfig reserves the filenameStyle key for this package's shared filename policy. It defaults to FilenameStyle.PascalCase, which enforces ComponentName.tsx and useThing.ts{,x} ownership files. Set filenameStyle: FilenameStyle.DashCase to enforce component-name.tsx and use-thing.ts{,x} instead:

import createOxlintConfig, { FilenameStyle } from "@alexgorbatchev/typescript-ai-policy/oxlint-config";

export default createOxlintConfig({
  filenameStyle: FilenameStyle.DashCase,
  ignorePatterns: ["coverage"],
});

When you run Oxlint manually, use Bun to launch the CLI:

bun --bun oxlint .

Treat bun --bun oxlint ... as the canonical invocation form for this package and for consumer repositories using these TypeScript config entrypoints.

What it enforces

At a glance, the shared policy enforces:

  • baseline guardrails such as strict equality and no any
  • component ownership files that export exactly one main component or one multipart component family, plus type-only secondary API, and live under canonical components/, templates/, or layouts/ directories using ComponentName.tsx by default or component-name.tsx when filenameStyle: FilenameStyle.DashCase is configured
  • hook ownership files that export exactly one main use* hook, plus type-only secondary API, and live as direct-child hooks/useThing.ts[x] files by default or hooks/use-thing.ts[x] when filenameStyle: FilenameStyle.DashCase is configured
  • JSX-only React component code instead of React.createElement(...)
  • matching Storybook files for component ownership files under sibling stories/ directories, with story support files limited to helpers.ts[x], fixtures.ts[x], or fixtures/
  • Storybook project support .tsx files under direct or nested .storybook/ paths without treating them as component ownership files
  • matching test files for hook ownership files under sibling __tests__/ directories, with test support files limited to helpers.ts[x], fixtures.ts[x], or fixtures/
  • typed Storybook meta with package-relative titles, typed story exports, and required play functions
  • deterministic component test ids such as ComponentName and ComponentName--child, plus required root test ids for exported ownership components
  • canonical component ownership directories (components/, templates/, layouts/) as the only product .tsx surface allowed to render raw intrinsic JSX or pass direct className / style props, with file-role carve-outs for story/test support and Storybook .storybook/ support files
  • strict boundaries between runtime code, test code, story code, and fixture code, including no imports from __tests__/ into runtime code and no type imports from constants.ts
  • test-file discipline: no skipped or focused tests, no conditional logic, no throw, no module mocking, no test-file exports, and no inline fixture bindings
  • fixture discipline: canonical location, single entrypoint, constrained export naming and export types, no local type declarations, and canonical fixture import paths
  • explicit type/value ownership rules for files such as index.ts, constants.ts, and types.ts
  • strict type and function-contract rules: I* interfaces only, no I* type aliases, no direct interface-to-type passthrough aliases, no trivial property-selector forwarding wrappers whose names merely restate the selected property, no inline type imports or inline structural type expressions, and indented multiline template literals
  • a policy stance that inline lint-disable comments are not an acceptable escape hatch for fixing violations

Lint-disable comments are not a valid repair strategy

Agents and developers are expected to satisfy the shared policy directly, not suppress it locally with comments such as // oxlint-disable-next-line or /* oxlint-disable */.

This package explicitly bans inline lint-disable comments for both ESLint and Oxlint. Treat this as a hard policy signal, not as an obstacle to bypass. The enforcement strategy assumes you will fix the underlying contract violation rather than suppressing the warning.

The important contract is simple:

  • do not use inline lint-disable comments to get around the shared policy
  • fix the code so it satisfies the rule set instead
  • if the policy itself is wrong, change the shared package deliberately rather than bypassing it locally

Storybook is the React component contract

For React components, this policy is intentionally story-first.

Every component ownership file must have a matching Storybook file, every story meta must be typed and use a package-relative title, and every exported story must be typed and include a play function unless !test removes the built-in Storybook test tag for that story. In practice, that makes Storybook the canonical artifact for component behavior:

  • the same story layer can back CI interaction coverage
  • the same stories also act as the human visual reference for the component
  • component structure and component verification stay in one place instead of drifting across separate ad-hoc test files

This package does not wire your CI for you, but it does enforce the repository shape required for Storybook-driven component verification.

Expected layout shape

The policy enforces canonical role directories inside your feature tree.

That means repositories can choose their feature boundaries, but component, story, hook, and test files still have fixed ownership locations:

  • component ownership .tsx files live under components/, templates/, or layouts/
  • nested subdirectories inside those component ownership areas are allowed but not required
  • non-story, non-test .tsx files must not render raw intrinsic JSX such as <div>, <span>, or <p> unless the file lives inside one of those canonical component ownership areas
  • direct className and style props are only allowed on raw HTML elements in files inside those canonical component ownership areas. Custom/capitalized components must not accept className or style props in any file.
  • Storybook project support .tsx files under .storybook/*.tsx and .storybook/**/*.tsx are not component ownership files and may use local Storybook wrapper markup
  • story files live under sibling stories/ directories, and that area is reserved for *.stories.tsx, helpers.ts[x], fixtures.ts[x], and fixtures/
  • exported runtime hooks whose names start with use live under direct-child hooks/ ownership files
  • test files live under sibling __tests__/ directories, and that area is reserved for *.test.ts[x], helpers.ts[x], fixtures.ts[x], and fixtures/
  • fixture entrypoints and fixture directories live under stories/ or __tests__/
  • component filenames match the exported PascalCase component name in ComponentName.tsx form by default, or component-name.tsx when filenameStyle: FilenameStyle.DashCase is configured
  • hook filenames match the exported use* hook name in useThing.ts[x] form by default, or use-thing.ts[x] when filenameStyle: FilenameStyle.DashCase is configured
  • index.ts is reserved for pure barrel re-exports only
  • constants.ts is for runtime values only
  • types.ts is for type-only exports only

Example:

feature/
├── components/
│   ├── AccountPanel.tsx
│   └── stories/
│       └── AccountPanel.stories.tsx
└── hooks/
    ├── useAccount.ts
    └── __tests__/
        └── useAccount.test.ts

Minimal config:

import createOxlintConfig from "@alexgorbatchev/typescript-ai-policy/oxlint-config";

export default createOxlintConfig();

With that config in place, routes, pages, feature views, and other product .tsx files must render imported components instead of raw DOM tags, and they must not pass direct className or style props. Raw intrinsic JSX and direct styling props stay on raw HTML elements inside canonical component ownership areas, story/test support files, or Storybook .storybook/ support files. Passing className or style props to custom components is banned everywhere.

In a consuming repository, use typescript-ai-policy check through your package manager's local binary runner to execute the shared formatter and linter checks against that repo.

When a consuming harness supports environment injection, configure that harness to run shell commands with AGENT=1 so typescript-ai-policy check emits agent-formatted oxlint output automatically for agent workflows and more token-efficient lint output.

CLI tooling

The package includes the typescript-ai-policy CLI. Its fix-semantic command is backed by tsc --lsp --stdio, and its guidance command prints authoritative repair guidance for the local @alexgorbatchev/* rules as a wrapped Markdown bullet list with bold rule names or as JSON.

Package-installed usage:

  • bun run typescript-ai-policy -- check — run the package formatter and linter checks in the consuming repository. When the consuming harness is configured to inject AGENT=1, the oxlint step uses agent formatting automatically for agent workflows and more token-efficient output.
  • bun run typescript-ai-policy -- guidance — print the published rule guidance that the package exposes for AI agents as a wrapped Markdown bullet list with bold rule names.
  • bun run typescript-ai-policy -- guidance --json — print the same published rule guidance as JSON objects with ruleName and resolved guidance fields.
  • bun run typescript-ai-policy -- fix-semantic <target-directory> — run Oxlint with this package's policy config, collect supported diagnostics, and apply semantic fixes to the target directory.
  • bun run typescript-ai-policy -- fix-semantic <target-directory> --dry-run — print the planned semantic-fix scope without mutating files.

The published guidance output is package-level repair guidance, not a repository-specific config dump. Agents should still inspect the consuming repository's actual oxlint.config.ts before applying file-specific guidance in another codebase.

Repository-local development usage:

  • bun run cli -- guidance — run the repository-local CLI entrypoint directly from TypeScript source.
  • bun run cli -- guidance --json — print the same repository-local guidance output as JSON.
  • bun run cli -- fix-semantic <target-directory> — run the repository-local CLI entrypoint for semantic fixes.
  • bun run fix:semantic -- <target-directory> — run the same fix-semantic command from this repository checkout while developing the package itself.

The repository-local development command uses Bun to execute the TypeScript source directly. The published npm package also uses a compiled Bun-targeted bin.

Today the framework applies three conservative semantic fixes:

  • @alexgorbatchev/interface-naming-convention — rename repository-owned interfaces to their required I* form when the existing name can be normalized safely.
  • @alexgorbatchev/no-i-prefixed-type-aliases — rename repository-owned type aliases to drop the interface-style I* prefix when the diagnostic resolves to a concrete type alias name safely.
  • @alexgorbatchev/test-file-location-convention — move misplaced .test.ts / .test.tsx files into a sibling __tests__/ directory as __tests__/basename.test.ts[x] and rewrite the moved file's relative imports.

The command and backend shape remain intentionally generic so more rule-backed semantic operations can be added later.

Learn more

Local package setup

This repository also consumes its own shared configs at the root:

  • oxfmt.config.ts
  • oxlint.config.ts