# Add Package

> Create or align a package in the Remix monorepo to match existing package conventions. Use when adding a brand new package under packages/, or when fixing an existing package's structure, test setup, TypeScript/build config, code style, and README layout to match the rest of Remix 3.

- Skill: `remix-run/add-package` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add remix-run/add-package`
- Raw SKILL.md: https://api.skillmd.com/api/skills/remix-run/add-package/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: remix-run (https://skillmd.com/u/remix-run)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/remix-run/add-package

---


# Add Package

## Overview

Use this skill to scaffold and standardize packages so they look and behave like the existing `@remix-run/*` packages. Follow this exactly when creating package files, public exports, tests, and docs.

## Workflow

1. Create the package directory and baseline files.

- Create `packages/<package-name>/`.
- Add:
  - `package.json`
  - `tsconfig.json`
  - `tsconfig.build.json`
  - `CHANGELOG.md`
  - `README.md`
  - `LICENSE`
  - `src/`
- For new packages, start `CHANGELOG.md` with `## Unreleased` as the first section to indicate changes are not released yet.

2. Set up `package.json` using monorepo conventions.

- Use:
  - `name`: `@remix-run/<package-name>`
  - `version` (for brand-new packages): `"0.0.0"`
  - `type`: `"module"`
  - `license`: `"MIT"`
  - `repository.directory`: `packages/<package-name>`
  - `homepage`: `https://github.com/remix-run/remix/tree/main/packages/<package-name>#readme`
- Include `files`:
  - `LICENSE`
  - `README.md`
  - `dist`
  - `src`
  - `!src/**/*.test.ts`
- Add standard scripts:
  - `build`: `tsgo -p tsconfig.build.json`
  - `clean`: `git clean -fdX`
  - `prepublishOnly`: `pnpm run build`
  - `test`: `remix test`
  - `test:bun`: `bun x --bun remix test`
  - `typecheck`: `tsgo --noEmit`
- Use baseline dev dependencies:
  - `"@remix-run/assert": "workspace:^"`
  - `"@remix-run/test": "workspace:^"`
  - `"@types/node": "catalog:"`
  - `"@typescript/native-preview": "catalog:"`
- Add `keywords` like existing packages (short, lowercase, feature-focused).

3. Define exports with `src` entry files only.

- In `exports`, map each public subpath to a dedicated file in `src`.
- Always include `./package.json`.
- Mirror each export in `publishConfig.exports` with `dist` output:
  - `types`: `./dist/<entry>.d.ts`
  - `default`: `./dist/<entry>.js`
- Rule: every export must have a `src` file that re-exports from `src/lib`.
  - Example: export `./foo` -> `src/foo.ts` -> `export { ... } from './lib/foo.ts'`
- Type-only exports may map only a `types` condition to `src/*.d.ts` and `dist/*.d.ts`.
- Runtime-specific exports may use package conditions before `default` when the runtime owns that condition, such as `node-hmr` for `remix/node-hmr/runtime`.
- If a package has type-only exports, add `node ../../scripts/copy-package-type-only-exports.ts .` to the package build script after `tsgo`.

4. Add TypeScript config files with shared defaults.

Use this `tsconfig.json` pattern:

```json
{
  "compilerOptions": {
    "strict": true,
    "lib": ["ES2024", "DOM", "DOM.Iterable"],
    "module": "ES2022",
    "moduleResolution": "Bundler",
    "target": "ESNext",
    "allowImportingTsExtensions": true,
    "rewriteRelativeImportExtensions": true,
    "verbatimModuleSyntax": true
  }
}
```

Use this `tsconfig.build.json` pattern:

```json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dist"
  },
  "include": ["src"],
  "exclude": ["src/**/*.test.ts"]
}
```

5. Implement source structure and test setup.

- Structure source as:
  - `src/<entry>.ts` for public entry points
  - `src/lib/*.ts` for implementation
  - `src/lib/*.test.ts` for tests (colocated with implementation)
- Tests use Remix's test runner:
  - `import * as assert from '@remix-run/assert'`
  - `import { describe, it } from '@remix-run/test'`
- Keep tests IDE-friendly:
  - Do not generate tests with loops/conditionals inside `describe()`.

6. Follow monorepo code style rules while implementing.

- Use `import type { ... }` and `export type { ... }` for types.
- Include `.ts` extensions in relative imports.
- Prefer `let` for locals; use `const` only at module scope.
- Never use `var`.
- Prefer function declarations/expressions for normal functions.
- Use arrow functions for callbacks; use concise callbacks when returning a single expression.
- Use object method shorthand (`method() {}`) instead of arrow properties.
- Use native class fields and `#private` members.
- Avoid Node-specific APIs when Web APIs are available.

7. Write README in the same style and section order as existing packages.

- Start with:
  - `# <package-name>`
  - One short paragraph describing purpose.
- Typical section order:
  - `## Features`
  - `## Installation`
  - `## Usage`
  - Optional deep-dive sections (only if needed)
  - `## Related Packages` (if applicable)
  - `## License`
- Installation instructions must always include installing the `remix` package.
- If using the package requires a peer dependency, installation instructions must also include that peer dependency in the command.
- Preferred installation pattern:

```sh
npm i remix
```

- Example when a peer dependency is required:

```sh
npm i remix <peer-dependency>
```

- Usage examples must always import from `remix` package exports, not from `@remix-run/<package-name>` directly.

- License section format:
  - `See [LICENSE](https://github.com/remix-run/remix/blob/main/LICENSE)`

8. Handle generated `remix` package updates deliberately.

- `packages/remix` is generated automatically in CI.
- Do not hand-edit `packages/remix/package.json` or `packages/remix/src/*`; run the generator when generated output is required.
- **When adding a new package**, add it to `packages/remix/manifest.json` before running the generator:
  - Add one entry per export: `"remix/<canonical-path>": "@remix-run/<package-name>"`,`"remix/<canonical-path>/foo": "@remix-run/<package-name>/foo"`.
  - Include type-only and runtime-condition exports that should be reachable through `remix/...`, such as `remix/<canonical-path>/types`.
  - Choose a domain-oriented canonical path (e.g. `remix/middleware/logger`, not `remix/logger-middleware`).
- If user asks for full surfacing, you can still update root `README.md` package list when applicable.

9. Validate before finishing.

- Run package checks:
  - `pnpm --filter @remix-run/<package-name> run typecheck`
  - `pnpm --filter @remix-run/<package-name> run test`
  - `pnpm --filter @remix-run/<package-name> run build`
- Run repo lint (required):
  - `pnpm run lint`
- Create `packages/<package-name>/.changes/` on demand and add or update a change file when requested by contribution workflow.
- For a brand-new package, the initial change file should use a `minor.` filename (for example, `minor.initial-release.md`) so the first release bumps `0.0.0` to `0.1.0`.

## Templates

Use this minimal `src/index.ts` style:

```ts
export { createThing, type ThingOptions } from './lib/thing.ts'
```

Use this minimal test style:

```ts
import * as assert from '@remix-run/assert'
import { describe, it } from '@remix-run/test'

import { createThing } from './thing.ts'

describe('createThing', () => {
  it('returns expected value', () => {
    let result = createThing()
    assert.equal(result, 'ok')
  })
})
```

