es-toolkit

GitHub

A modern JavaScript utility library that's 2-3 times faster and up to 97% smallerβ€”a major upgrade to lodash.

11,281 stars TypeScript
RAW Rules

AGENTS.md

# es-toolkit LLM coding agent instructions

This file gives LLM coding agents the context they need to contribute to es-toolkit. Read it before making changes, and follow it together with [`.github/CONTRIBUTING.md`](./.github/CONTRIBUTING.md) (and its translations).

## Project overview

es-toolkit is a modern, high-performance JavaScript utility library with a small bundle size and strong type annotations. It provides a curated set of utilities that are difficult to write with built-in JavaScript methods but are commonly needed in real-world projects, such as [`delay`](https://es-toolkit.dev/reference/promise/delay.html), [`windowed`](https://es-toolkit.dev/reference/array/windowed.html), [`keyBy`](https://es-toolkit.dev/reference/array/keyBy.html), [`mapValues`](https://es-toolkit.dev/reference/object/mapValues.html), [`camelCase`](https://es-toolkit.dev/reference/string/camelCase.html), and [`toSnakeCaseKeys`](https://es-toolkit.dev/reference/object/toSnakeCaseKeys.html).

The library is split into two entry points:

- **`es-toolkit`** β€” the strict, opinionated main library. Focused on the 85% use case with a simple interface, no complex options, and modern JavaScript semantics.
- **`es-toolkit/compat`** β€” a Lodash-compatible variant intended to make migration from Lodash easy. Compat is feature-complete; only behavior fixes against Lodash are accepted, not new functions.

es-toolkit is a zero-dependency library and ships with no runtime dependencies.

## Development environment

- **Primary environment**: Node.js v24 (see `.nvmrc` for the exact version)
- **Recommended editor**: Visual Studio Code
- **Package manager**: Yarn v4, installed via [Corepack](https://yarnpkg.com/getting-started/install). See [the package manager section in CONTRIBUTING.md](./.github/CONTRIBUTING.md#package-manager) for details.

To get started:

```bash
corepack enable
yarn install
```

Common commands:

```bash
yarn vitest run                   # Run all tests
yarn vitest run src/array/chunk   # Run tests for a specific function
yarn lint                         # ESLint
tsc --noEmit                      # Typecheck
```

## Repository structure

```
src/
  {category}/{fn}.ts          Implementation for the main `es-toolkit` library
  {category}/{fn}.spec.ts     Unit tests (vitest)
  compat/{category}/{fn}.ts   Lodash-compatible variant under `es-toolkit/compat`
  index.ts                    Top-level barrel re-exports
  {category}/index.ts         Per-category barrel re-exports
docs/
  reference/{category}/{fn}.md          English reference docs
  ko/reference/{category}/{fn}.md       Korean reference docs
  ja/reference/{category}/{fn}.md       Japanese reference docs
  zh_hans/reference/{category}/{fn}.md  Simplified Chinese reference docs
benchmarks/                   Vitest benchmark suite
tests/types/                  Type tests comparing `es-toolkit/compat` with `@types/lodash` (run with `yarn workspace type-tests test`)
.github/CONTRIBUTING.md       Contribution guide (English / Korean / Simplified Chinese)
CHANGELOG.md                  User-facing changelog
```

Categories include `array`, `bigint`, `function`, `math`, `object`, `predicate`, `promise`, `set`, `string`, `util`, `error`, and `map`.

## Principles

es-toolkit values **performance**, **simplicity**, and **detailed documentation** over a wide surface area of features and options.

- **Performance**: every function should match or beat alternative libraries. New features must come with benchmarks.
- **Simplicity**: provide the simplest interface for the 85% use case; do not add complex options for every edge case.
- **Don't reimplement modern JS**: skip functions that are already covered by built-ins (`Array.isArray`, `Number.isNaN`, `Math.min`, `typeof value === 'number'`, etc.) or by TC39 proposals at Stage 3 or above.
- **Accurate types**: match the inference behavior of TypeScript's `strict` mode.
- **Two entry points, two policies**: `es-toolkit` is the opinionated API; `es-toolkit/compat` mirrors Lodash for migration. Compat is feature-complete β€” only behavior fixes against Lodash are accepted, not new functions.

For the full text, see [Section 1 of CONTRIBUTING.md](./.github/CONTRIBUTING.md#1-our-design-principles).

## Coding conventions

- Prefer `for` loops over `reduce`. Local mutability is fine.
- Prefer built-in JavaScript over custom helpers (`Array.isArray()` over `isArray()`, `typeof value === 'string'` over `isString()`).
- Use short type parameter names: `T` for elements, `K` for keys, `E` for errors.
- Use `readonly T[]` for array parameters that are not mutated.
- Write detailed JSDoc with `@template`, `@param`, `@returns`, `@throws`, and `@example` blocks.

For the full text, see [Section 2 of CONTRIBUTING.md](./.github/CONTRIBUTING.md#2-coding-conventions).

## Development workflow

When adding or changing a function, follow this order:

1. **Add the implementation** under `src/{category}/{fn}.ts` (or `src/compat/{category}/{fn}.ts` for compat-only fixes). Re-export it from `src/{category}/index.ts` and `src/index.ts`.
2. **Add unit tests** with vitest in `src/{category}/{fn}.spec.ts`. Cover the happy path, edge cases (empty input, `null`/`undefined`, large input), and any Lodash-specific behavior in compat.
3. **Run the unit tests**:
   ```bash
   yarn vitest run src/{category}/{fn}
   ```
   Then run the full suite (`yarn vitest run`), `yarn lint`, and `tsc --noEmit` before opening the PR.
4. **Add documentation in all four languages** under `docs/`:

   - `docs/reference/{category}/{fn}.md` (English)
   - `docs/ko/reference/{category}/{fn}.md` (Korean, ν•΄μš”μ²΄)
   - `docs/ja/reference/{category}/{fn}.md` (Japanese)
   - `docs/zh_hans/reference/{category}/{fn}.md` (Simplified Chinese)

   See `docs/CLAUDE.md` for translation tables, and the [Writing Documentation section in CONTRIBUTING.md](./.github/CONTRIBUTING.md#5-writing-documentation) for the template and placeholder rules.

## Documentation standards

- Include JSDoc comments for every public API. Keep `@template`, `@param`, `@returns`, `@throws`, and `@example` up to date.
- Update the documentation whenever you change a public API. Keep all four language versions in sync β€” never leave one stale.
- Include realistic examples for new features. Prefer descriptive variable names over magic values so readers can infer the interface from the example.

## Pull request standards

Before opening a pull request, check [what we accept](./.github/CONTRIBUTING.md#41-what-we-accept). New functions need an accepted discussion first, performance work needs benchmark results, Lodash behavior fixes need a test that fails without the change, and refactoring-only changes are not accepted.

PR titles follow `<type>[function names]: <description>`. See [Section 4 of CONTRIBUTING.md](./.github/CONTRIBUTING.md#4-pull-requests) for the type list.

Use the following template for the PR body:

```markdown
## Summary

{Related issues if any}
{Concise summary}

## Changes

{Concise explanation of the code changes, in bullet points}

## Benchmark results

{Only for performance changes: benchmark output for `main` and for this branch. Remove this section otherwise.}
```

Do not paste test output into the PR body. CI runs the test suite on every pull request, so the results are already visible there. Benchmarks are the exceptionβ€”nothing in CI runs them, so a performance change has to bring its own numbers.

## Adding dependencies

es-toolkit is a **zero-dependency** library. Do not add anything to `dependencies` or `peerDependencies`. Only `devDependencies` are acceptable, and even there, prefer to avoid new packages unless they are clearly necessary for tooling.

## Changelog

User-facing changes go into [`CHANGELOG.md`](./CHANGELOG.md). Keep the file readable as a release notes document for users, not as a commit log.

Conventions:

- **Reverse chronological order** β€” newest version at the top.
- Each version is a heading: `## Version v{version}`, followed by a `Released on {date}.` line.
- Use `-` for list items. Wrap lines at roughly 80 columns and indent continuations with 4 spaces.
- Write **user-facing descriptions**: what changed, why it matters, and what users should do. Avoid implementation jargon.
- Reference PRs with `[#123]` markers inline. When a section has many references, you may add reference link definitions at the end of that section in the form `[#123]: https://github.com/toss/es-toolkit/pull/123`.
- For external contributors, credit them on the line: `[#123] by @username`.
- End each version section with a thank-you line:

  > We sincerely thank @username1, @username2, and @username3 for their contributions. We appreciate your great efforts!