Build and Typecheck Commands
Requires build and type checks to catch compilation and static typing problems.
Scenario
You have a TypeScript library that is consumed by several internal applications.
Developers frequently make changes that pass linting but fail during TypeScript compilation or package builds.
The project therefore wants coding agents to distinguish between:
- linting;
- type checking;
- building;
- testing.
The repository uses:
- TypeScript
- pnpm
- tsup
- ESLint
- Vitest
Repository Structure
shared-sdk/
├── src/
│ ├── client.ts
│ ├── errors.ts
│ ├── index.ts
│ └── types.ts
├── tests/
│ └── client.test.ts
├── package.json
├── tsconfig.json
├── tsup.config.ts
└── AGENTS.md
Relevant scripts:
{
"scripts": {
"build": "tsup",
"lint": "eslint .",
"typecheck": "tsc --noEmit",
"test": "vitest run"
}
}
AGENTS.md
# Project Instructions
## Development
- Use `pnpm`.
- Do not create npm or Yarn lockfiles.
## Validation
For TypeScript source changes:
- Run `pnpm typecheck`.
- Run tests relevant to the changed behavior.
Run `pnpm build` when changes affect:
- public exports;
- package entry points;
- generated declarations;
- build configuration.
Before completing substantial changes, run:
- `pnpm lint`
- `pnpm typecheck`
- `pnpm test`
- `pnpm build`
What This Does
This file tells the agent that the repository has several different validation mechanisms and that they catch different classes of problems.
For example:
pnpm lint
may pass while:
pnpm typecheck
fails because of an incompatible TypeScript type.
Likewise, both may pass while:
pnpm build
fails because the package entry point or build configuration is incorrect.
The instructions also distinguish between validation that should happen for most TypeScript changes and validation that becomes particularly important when package boundaries change.
What This Does NOT Do
The file does not pretend that every command provides the same kind of confidence.
For example:
- Run `pnpm lint` to verify the application works.
would be misleading.
Linting primarily checks configured static rules. It does not prove that:
- TypeScript compilation succeeds;
- runtime behavior is correct;
- package output can be produced;
- tests pass.
The file also does not require the agent to understand the internal implementation of tsup.
The project script remains the interface:
pnpm build
Why These Instructions Matter
Consider changing the package's public exports:
export { ApiClient } from "./client";
export type { ApiClientOptions } from "./types";
The source file may look valid.
Linting may pass.
Tests may even pass because they import internal modules directly.
But the published package could still be broken if its build output or declarations are incorrect.
That is why this repository explicitly says:
Run `pnpm build` when changes affect:
- public exports;
- package entry points;
- generated declarations;
- build configuration.
The validation requirement follows the risk introduced by the change.
Key Decisions
Lint, typecheck, build, and test are different
Think of them as different questions:
Lint → Does the code follow configured static rules?
Typecheck → Are TypeScript relationships valid?
Test → Does tested behavior still work?
Build → Can the distributable artifact be produced?
One command should not automatically be treated as a substitute for another.
Match validation to the change
A documentation-only edit may not require the same validation as changing:
src/index.ts
or:
tsup.config.ts
Instructions become more useful when they explain when a command matters.
Use repository scripts
Prefer:
pnpm build
over manually reproducing the underlying build invocation.
The repository owns the implementation of that script.
When to Use This Pattern
Use this pattern when:
- the project has a compilation or packaging step;
- type checking is separate from building;
- public exports matter;
- a successful lint run is not sufficient validation;
- different changes require different levels of verification.
It is especially useful for libraries, SDKs, packages, and strongly typed applications.