All skills
antfu avatar

/antfu

@feb0f3a official
by Anthony Fuantfu/skills6k stars
336

Anthony Fu's opinionated tooling and conventions for JavaScript/TypeScript projects. Use when setting up new projects, configuring ESLint/Prettier alternatives, monorepos, library publishing, or when the user mentions Anthony Fu's preferences.

Use this Skill: https://skilld.dev/gh/antfu/skills/antfu

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

SKILL.md

≈63 tokens for metadata: the name and description. ≈1.9k when used: this file. ≈5.1k more on demand in 5 files.

Description uses 3.1% of example budget

Before choosing a Skill, your Agent reads its name and description. All available Skills share that space.

  • A shorter description leaves more room for other Skills. This entry exceeds our 1% size suggestion.

In our Claude Code example, all Skill names and descriptions share 8,000 characters. This Skill uses ≈251 characters, or 3.1%.

The 1% threshold is a size suggestion. Longer descriptions can still fit.

Your model, settings, and other Skills decide how much text your Agent can read.

Example settings and source

The example uses a 200k-token context and default Claude Code settings. The count includes the name, description, separators, and when_to_use when present. Codex also counts local file paths.

Skit's source and limits: Codex 0.160.1, Claude Code 2.1.292.

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

Command Description
ni Install dependencies
ni <pkg> / ni -D <pkg> Add dependency / dev dependency
nr <script> Run script
nu Upgrade dependencies
nun <pkg> Uninstall dependency
nci Clean 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:

Catalog Purpose
prod Production dependencies
inlined Bundler-inlined dependencies
dev Dev tools (linter, bundler, testing)
frontend Frontend libraries

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


References

Topic Description Reference
ESLint Config Framework support, antislop, formatters, rule overrides, VS Code settings antfu-eslint-config
Project Setup .gitignore, GitHub Actions, OIDC trusted publishing, VS Code extensions setting-up
App Development Vue/Nuxt/UnoCSS conventions, auto-import control, Storybook component testing app-development
Library Development tsdown bundling, pure ESM publishing, publint, API snapshots library-development
Monorepo pnpm workspaces, centralized alias, Turborepo monorepo

Source: SKILL.md on GitHub

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

No alerts9d5 checks · Risk SAFE
  • Gen Agent Trust Hub9d

    This skill defines Anthony Fu's opinionated tooling and conventions for JavaScript/TypeScript development, covering ESLint configurations, monorepo management, and library publishing workflows. It facilitates setting up standard project structures, formatting rules, and automated CI/CD pipelines using recommended packages and GitHub Actions.

  • Socket9d

    No alerts

  • Snyk9d

    Risk: LOW · No issues

  • Runlayer7mo

    6 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at feb0f3a. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 2 weeks ago
metadata
{
  "author": "Anthony Fu",
  "version": "2026.09.30"
}
  • TypeScript
  • eslint
  • vitest
  • pnpm
  • monorepo
  • esnext
  • linting
  • conventions

README badge

README badge for antfu/skills/antfu

Anthony Fu's coding conventions and tooling setup for JavaScript/TypeScript projects, covering file organization, TypeScript strictness, ESLint configuration, and Vitest practices. Use when initializing projects, configuring linters, setting up monorepos with pnpm workspaces, or implementing Anthony Fu's published standards.

Generated from the current SKILL.md.

Does this skill apply to my JavaScript project if I'm not using TypeScript?
The skill is built around TypeScript conventions, but many practices (file organization, ESLint setup with @antfu/eslint-config, testing structure) apply to JavaScript projects too. Some guidance like explicit return types is TypeScript-specific.
What package manager does this skill assume?
The skill assumes pnpm, as shown in the git hooks example and pnpm-workspace.yaml references. The @antfu/ni tool abstracts package manager commands, but pnpm catalogs and workspace setup are pnpm-specific.
Does this cover frontend frameworks like Vue and React?
Yes, the skill includes references for Vue/Nuxt conventions and UnoCSS, but React-specific guidance is not detailed in the main content. The referenced app-development section likely covers framework patterns.
What testing framework does this skill use?
The skill specifies Vitest for testing, with conventions like `foo.test.ts` naming, `describe`/`it` API, and snapshot matching.
Can I use this skill for library publishing?
Yes, the skill includes a reference section on library development covering tsdown bundling and pure ESM publishing patterns, though those details are in a separate reference document.

Generated from the current SKILL.md. These answers refresh after source changes.