antfu

SkillDev tools

This skill gives your AI Anthony Fu's tooling choices and coding conventions for JavaScript and TypeScript projects. Once added, your AI can set up new projects and configure tooling to match his preferences, so your code follows a consistent style from day one.

Use antfu in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add antfu and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the antfu skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

After adding it, ask your AI to set up a new JavaScript or TypeScript project, or mention Anthony Fu's preferences when you want linting, monorepos, or library publishing configured his way.

What your AI can do with it

  • Set up new JavaScript or TypeScript projects using Anthony Fu's conventions
  • Configure linting and formatting, including ESLint and Prettier alternatives
  • Set up monorepos
  • Prepare libraries for publishing
  • Apply Anthony Fu's tooling preferences when you mention them by name

What this skill tells your AI

The instructions your AI receives, as published by antfu/skills in skills/antfu/SKILL.md and read by Ahel’s review.

Reference template: antfu/starter-ts. When scaffolding a new TypeScript project, mirror its package.json scripts, eslint.config.js, knip.json, tsdown.config.ts and workflows rather than inventing a new layout.

Coding Practices

Code Organization

  • Single responsibility: Each source file should have a clear, focused scope/purpose
  • Split large files: Break files when they become large or handle too many concerns
  • Type separation: Always separate types and interfaces into types.ts or types/*.ts
  • Constants extraction: Move constants to a dedicated constants.ts file

Runtime Environment

  • Prefer isomorphic code: Write runtime-agnostic code that works in Node, browser, and workers whenever possible
  • Clear runtime indicators: When code is environment-specific, add a comment at the top of the file:
// @env node
// @env browser

TypeScript

  • Explicit return types: Declare return types explicitly when possible
  • Avoid complex inline types: Extract complex types into dedicated type or interface declarations

Explicitness

Favor explicit, traceable code over implicit "magic". A reader (human or agent) should be able to follow where every name comes from without running tooling.

  • Explicit imports: Prefer explicit import statements. Avoid auto-imports — when a framework provides them (e.g. Nuxt/Nitro), turn them off for new projects (see app-development).
  • No path aliases by default: Use relative imports (./foo, ../bar). Only use path aliases (@/, ~/, #imports, etc.) when they are already configured in the project; don't introduce new ones for greenfield code.

Comments

  • Avoid unnecessary comments: Code should be self-explanatory
  • Explain "why" not "how": Comments should describe the reasoning or intent, not what the code does

Testing (Vitest)

  • Test files: foo.ts → foo.test.ts (same directory)
  • Use describe/it API (not test)
  • Use toMatchSnapshot for complex outputs
  • Use toMatchFileSnapshot with explicit path for language-specific snapshots

Tooling Choices

@antfu/ni Commands

CommandDescription
niInstall dependencies
ni <pkg> / ni -D <pkg>Add dependency / dev dependency
nr <script>Run script
nuUpgrade dependencies
nun <pkg>Uninstall dependency
nciClean install (pnpm i --frozen-lockfile)
nlx <pkg>Execute package (npx)

Checking npm Package Versions

Use fast-npm-meta to look up the latest version of a package — it queries a small metadata endpoint instead of downloading the full registry payload (which can be megabytes per package).

nlx fast-npm-meta version vite              # 7.3.1
nlx fast-npm-meta version "nuxt@^3.5"       # 3.5.22 — range-aware
nlx fast-npm-meta version vite nuxt vue     # multiple at once
nlx fast-npm-meta version vite --json       # JSON for scripting
nlx fast-npm-meta full vite                 # full version list + dist-tags

Prefer this over npm view <pkg> version when you only need the latest version, and over reading package.json from the registry directly.

TypeScript Config

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true
  }
}

ESLint Setup

// eslint.config.js
import antfu from '@antfu/eslint-config'

export default antfu({
  type: 'lib', // or 'app' (default)
  pnpm: true, // enforce pnpm catalogs in package.json
  antislop: true, // flag redundant/duplicated AI-style code, ban explicit `any`
})

Always enable antislop: true. It requires eslint-plugin-slop and eslint-plugin-sonarjs as dev dependencies.

For detailed configuration options: antfu-eslint-config

Knip

Use Knip to catch unused files, exports and dependencies — the linter only sees one file at a time.

// knip.json
{
  "$schema": "https://unpkg.com/knip@6/schema.json",
  "project": ["src/**/*.ts"],
  "ignoreDependencies": []
}

Fix what Knip reports by deleting; only add to ignoreDependencies for tools invoked outside package.json scripts (e.g. taze).

Scripts and the ci Gate

Every project exposes a ci script that runs all checks in one command:

{
  "scripts": {
    "build": "tsdown",
    "lint": "eslint --cache",
    "typecheck": "tsc",
    "knip": "knip",
    "test": "pnpm run build && vitest",
    "ci": "pnpm run lint && pnpm run typecheck && pnpm run knip && pnpm run test --run"
  }
}

Before every commit, run nr lint --fix to format, then nr ci and make sure it passes. Do not commit with a failing ci; fix the root cause instead of silencing rules or adding ignores.

Git Hooks

simple-git-hooks + nano-staged. The pre-commit hook runs the full ci gate; prepare also installs agent skills via skills-npm:

{
  "scripts": {
    "prepare": "git config core.hooksPath .githooks && simple-git-hooks && skills-npm"
  },
  "simple-git-hooks": {
    "pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && pnpm run ci && pnpx nano-staged"
  },
  "nano-staged": {
    "*": "eslint --fix --no-warn-ignored"
  }
}

Add .githooks to .gitignore and simple-git-hooks: true under allowBuilds in pnpm-workspace.yaml.

skills-npm

skills-npm symlinks agent skills shipped inside installed npm packages (and fetches those declared in a skills field) into the agent's skills directory on every install. Install as a dev dependency and wire it into prepare as above; add skills/npm-* to .gitignore. Commit the generated skills-npm-lock.json.

Publishing

Prefer npm Trusted Publishing (OIDC) over NPM_TOKEN secrets: releases run on CI from a v* tag via release.yml with id-token: write, and nr release (bumpp) only bumps, tags and pushes. Details: setting-up.

pnpm Catalogs

Use named catalogs in pnpm-workspace.yaml for version management:

CatalogPurpose
prodProduction dependencies
inlinedBundler-inlined dependencies
devDev tools (linter, bundler, testing)
frontendFrontend libraries

Avoid the default catalog. Catalog names can be adjusted per project needs.


References

TopicDescriptionReference
ESLint ConfigFramework support, antislop, formatters, rule overrides, VS Code settingsantfu-eslint-config
Project Setup.gitignore, GitHub Actions, OIDC trusted publishing, VS Code extensionssetting-up
App DevelopmentVue/Nuxt/UnoCSS conventions, auto-import control, Storybook component testingapp-development
Library Developmenttsdown bundling, pure ESM publishing, publint, API snapshotslibrary-development
Monorepopnpm workspaces, centralized alias, Turborepomonorepo

Signals

GitHub stars
6k
Forks
335
Last commit
Sep 2026

Ahel review

  • K1binfo
    installs-packages (in references/antfu-eslint-config.md)

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Item type
skill
Key
antfu
Source
github.com/antfu/skills