/antfu
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.
$ npx -y skills add antfu/skills --skill antfu --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/antfu
Context preview
The summary Claude sees to decide when to auto-load this skill.
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.
SKILL.md
antfu.SKILL.mdname: antfu
description: 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.
metadata:
author: Anthony Fu
version: "2026.06.22"
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](references/app-development.md)).
- **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`](https://github.com/antfu/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.mjs
import antfu from '@antfu/eslint-config'
export default antfu()
When completing tasks, run `pnpm run lint --fix` to format the code and fix coding style.
For detailed configuration options: [antfu-eslint-config](references/antfu-eslint-config.md)
Git Hooks
{
"simple-git-hooks": {
"pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && npx lint-staged"
},
"lint-staged": { "*": "eslint --fix" },
"scripts": {
"prepare": "npx simple-git-hooks"
}
}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, formatters, rule overrides, VS Code settings | [antfu-eslint-config](references/antfu-eslint-config.md) | | Project Setup | .gitignore, GitHub Actions, VS Code extensions | [setting-up](references/setting-up.md) | | App Development | Vue/Nuxt/UnoCSS conventions, auto-import control, Storybook component testing | [app-development](references/app-development.md) | | Library Development | tsdown bundling, pure ESM publishing | [library-development](references/library-development.md) | | Monorepo | pnpm workspaces, centralized alias, Turborepo | [monorepo](references/monorepo.md) |
Read more
name: antfu description: 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. metadata: author: Anthony Fu version: "2026.06.22"
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](references/app-development.md)).
- **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`](https://github.com/antfu/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.mjs import antfu from '@antfu/eslint-config' export default antfu()
When completing tasks, run `pnpm run lint --fix` to format the code and fix coding style.
For detailed configuration options: [antfu-eslint-config](references/antfu-eslint-config.md)
Git Hooks
{
"simple-git-hooks": {
"pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && npx lint-staged"
},
"lint-staged": { "*": "eslint --fix" },
"scripts": {
"prepare": "npx simple-git-hooks"
}
}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, formatters, rule overrides, VS Code settings | [antfu-eslint-config](references/antfu-eslint-config.md) | | Project Setup | .gitignore, GitHub Actions, VS Code extensions | [setting-up](references/setting-up.md) | | App Development | Vue/Nuxt/UnoCSS conventions, auto-import control, Storybook component testing | [app-development](references/app-development.md) | | Library Development | tsdown bundling, pure ESM publishing | [library-development](references/library-development.md) | | Monorepo | pnpm workspaces, centralized alias, Turborepo | [monorepo](references/monorepo.md) |
A curated collection of Agent Skills reflecting Anthony Fu's preferences, experience, and best practices, along with usage documentation for the tools.
Repo: antfu/skills
Other skills on antfu-skills.
- /antfu-design
antfu-style design conventions, broadened. UnoCSS-first, class-based semantic tokens with dual light/dark for tooling and devtools UIs, plus design-read, anti-slop, and micro-interaction polish for landing pages and product surfaces. Use when building or refactoring any
Open skill - /nitro
Nitro is the framework-agnostic server toolkit (powering Nuxt) for building and deploying web servers anywhere. Use when working with nitro.config, server routes/event handlers, route rules, caching, storage, tasks, websockets, or deploying to Node/Bun/Deno/Cloudflare/Vercel.
Open skill - /nuxt
Nuxt full-stack Vue framework with SSR, auto-imports, and file-based routing. Use when working with Nuxt apps, server routes, useFetch, middleware, or hybrid rendering.
Open skill - /pinia
Pinia official Vue state management library, type-safe and extensible. Use when defining stores, working with state/getters/actions, or implementing store patterns in Vue apps.
Open skill - /pnpm
Node.js package manager with strict dependency resolution. Use when running pnpm specific commands, configuring workspaces via pnpm-workspace.yaml, or managing dependencies with catalogs, patches, overrides, config dependencies, or the global virtual store.
Open skill - /slidev
Create and present web-based slidedecks for developers using Slidev with Markdown, Vue components, code highlighting, animations, and interactive features. Use when building technical presentations, conference talks, code walkthroughs, teaching materials, or developer decks.
Open skill

