lintcn
raw JSON → 0.9.0 verified Fri May 01 auth: no javascript
A CLI tool for browsing, installing, and managing custom TypeScript lint rules as local Go source files, inspired by shadcn for UI components. Current version 0.9.0; releases appear every 2–3 weeks. Unlike ESLint plugins or convention-based linters, lintcn copies rule source into your project so you fully own and can customize each rule. Powered by tsgolint (Go-based TypeScript linter with type-aware analysis). Minimizes false positives by running only explicitly added rules. Supports automatic fixes, warning severity, and snapshot testing.
Common errors
error Error: Cannot find module 'lintcn' ↓
cause Attempting to import or require lintcn as a library without installing it.
fix
Run 'npm install -D lintcn' to add it as a devDependency.
error Error: Unknown command: install ↓
cause Using non-existent subcommand 'install' instead of 'add'.
fix
Use 'npx lintcn add <url>' to install a rule.
error package declaration must match folder name ↓
cause When writing a custom rule, the Go package name in the .go file must equal the folder name under .lintcn/.
fix
Rename the folder to match the package declaration, or edit the package declaration to match the folder name (e.g., package no_unhandled_error in folder .lintcn/no_unhandled_error/).
error Rule import path 'internal/rule' not found ↓
cause Using outdated import path for the tsgolint rule API (changed in v0.4.0).
fix
Replace 'github.com/typescript-eslint/tsgolint/internal/rule' with 'github.com/typescript-eslint/tsgolint/pkg/rule'.
error lintcn lint: tsgolint version flag traversal detected ↓
cause Providing an invalid --tsgolint-version value that doesn't match the expected pattern (e.g., starting with 'v' followed by digits and dots).
fix
Use a valid version like 'v0.9.2' for --tsgolint-version.
Warnings
gotcha lintcn lint exits with 0 when no .lintcn/ directory exists; prints a helpful message instead of failing. Do not rely on exit code for presence of rules. ↓
fix Check for .lintcn/ directory explicitly in CI scripts if you require rules to be installed.
breaking Rule folder structure changed from flat .lintcn/*.go to subfolders .lintcn/{rule_name}/*.go in v0.6.0. Existing rules must be moved to subfolders. ↓
fix For each rule file in .lintcn/, move it into a new subfolder named after the rule (snake_case). The Go package declaration inside the file should match the folder name.
gotcha By default only warning rules with severity 'warn' do not fail CI; error severity rules exit with code 1 even if only one error is found. ↓
fix Use --all-warnings to see all warnings, and configure rule severity via // lintcn:severity warn in rule source.
security Path traversal vulnerability in --tsgolint-version flag allowed arbitrary file read via version string like '../../etc'. Fixed in v0.5.0 by validating version pattern. ↓
fix Update to v0.5.0 or later. If using older version, avoid using --tsgolint-version with untrusted input.
deprecated Rule import paths changed from 'internal/rule' to 'pkg/rule' in v0.4.0. Old rule files using internal/rule will fail to compile. ↓
fix Update rule Go files: replace 'github.com/typescript-eslint/tsgolint/internal/rule' with 'github.com/typescript-eslint/tsgolint/pkg/rule' (and similarly for internal/utils to pkg/utils).
breaking In v0.3.0, lintcn changed from running all 44 built-in tsgolint rules to running only custom rules in .lintcn/. Projects relying on built-in rules must explicitly add each rule needed. ↓
fix Use npx lintcn add to add each desired rule from the tsgolint repository. Alternatively, configure a separate tsgolint run for built-in rules.
gotcha Concurrent lintcn lint runs can corrupt each other's Go build workspace if not using unique content-hash workspaces. Fixed in v0.5.0 via per-content-hash workspaces. ↓
fix Upgrade to v0.5.0 or later to avoid intermittent failures when running multiple lintcn processes simultaneously.
Install
npm install lintcn yarn add lintcn pnpm add lintcn Imports
- default wrong
const lintcn = require('lintcn'); // CJS require fails: package is ESM-onlycorrectimport lintcn from 'lintcn' - CLI binary wrong
npx lintcn install <url> // 'install' is not a valid subcommand; use 'add'correctnpx lintcn add <url> - lintcn wrong
import { lintcn } from 'lintcn' // Named export 'lintcn' does not exist; use default importcorrectimport lintcn from 'lintcn'
Quickstart
const { execSync } = require('child_process');
// Install lintcn as devDependency
execSync('npm install -D lintcn', { stdio: 'inherit' });
// Add a rule from tsgolint repository
execSync('npx lintcn add https://github.com/oxc-project/tsgolint/blob/main/internal/rules/no_floating_promises/no_floating_promises.go', { stdio: 'inherit' });
// Lint the TypeScript project
execSync('npx lintcn lint --tsconfig tsconfig.json', { stdio: 'inherit' });
// List installed rules
execSync('npx lintcn list', { stdio: 'inherit' });