Context
Subpath exports are defined in package.json under the exports field. Each subpath maps to a source entry point that gets compiled to dist/. The exports catalog in CLAUDE.md/AGENTS.md must stay in sync with package.json.
The build uses tsconfig.build.json (not tsconfig.json) with rootDir: ./src and include: ["src/**/*"]. This means every source file at src/foo/bar.ts compiles to dist/foo/bar.js — the dist/ path in each export entry must match wherever tsc produces the compiled output for the named source file. Choose your source file location to produce the dist/ path you want in the export entry.
Steps
Create the entry point source file under
src/(e.g.,src/utils/new-util.ts)Add the subpath to
package.jsonexports, mirroring the source path:// source: src/utils/new-util.ts → dist: dist/utils/new-util.js "./newutil": { "types": "./dist/utils/new-util.d.ts", "import": "./dist/utils/new-util.js" }Update the exports catalog in both
CLAUDE.mdandAGENTS.md— add a row to the table. These files must stay byte-identical; the simplest approach iscp CLAUDE.md AGENTS.mdafter editingBuild with
bun run buildto generatedist/outputVerify the export resolves through the package's
exportsmap:# Confirm the compiled file exists at the expected dist path ls dist/utils/new-util.js # Confirm the subpath export resolves correctly (tests the exports map, not just the dist file) bun -e "import('@cyanheads/mcp-ts-core/newutil').then(m => console.log(Object.keys(m)))"Run
bun run devcheckto verify
Naming conventions
| Convention | Rule |
|---|---|
| Subpath | all-lowercase, no underscores (e.g., utils, storage/types, testing/fuzz) |
| Source file | kebab-case (e.g., error-handler.ts) |
| Export name | camelCase for values, PascalCase for types |
Checklist
- Source entry point file created with JSDoc header
- Subpath added to
package.jsonexportswithtypesandimportconditions - Exports catalog updated in both
CLAUDE.mdandAGENTS.md(must be byte-identical) - If the new export has optional peer dependencies: entries added to both
peerDependenciesandpeerDependenciesMetainpackage.json -
bun run buildsucceeds - Compiled file exists at expected
dist/path and subpath import resolves correctly - Integration test at
tests/integration/package-consumer.int.test.tsupdated: new subpath added to the import spec list andtoHaveLengthcount incremented -
bun run devcheckpasses