@codedrifters/configulator 0.0.250 → 0.0.252
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1327
- package/lib/index.d.mts +3 -3
- package/lib/index.d.ts +3 -3
- package/lib/index.js +3 -3
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +3 -3
- package/lib/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,1330 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @codedrifters/configulator
|
|
2
2
|
|
|
3
|
-
A library of [Projen](https://projen.io/) components used by CodeDrifters to manage repository configuration across
|
|
3
|
+
A library of [Projen](https://projen.io/) components used by CodeDrifters to manage repository configuration across projects. Configulator extends standard Projen configurations with preferred defaults and provides shared project types (`MonorepoProject`, `TypeScriptProject`), a PNPM/Turborepo integration, and an `AgentConfig` API for single-source AI assistant configuration.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Documentation:** See the [@codedrifters/configulator docs](../../../docs/src/content/docs/packages/@codedrifters/configulator/index.md) in the monorepo's Starlight site.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- [What is Projen?](#what-is-projen)
|
|
9
|
-
- [What is Configulator?](#what-is-configulator)
|
|
10
|
-
- [Project Types](#project-types)
|
|
11
|
-
- [MonorepoProject](#monorepoproject)
|
|
12
|
-
- [TypeScriptProject](#typescriptproject)
|
|
13
|
-
- [Usage Patterns](#usage-patterns)
|
|
14
|
-
- [Configuration Options](#configuration-options)
|
|
15
|
-
- [Turbo Repo](#turbo-repo)
|
|
16
|
-
- [PNPM Workspace](#pnpm-workspace)
|
|
17
|
-
- [Updating VERSION constants](#updating-version-constants)
|
|
18
|
-
- [File Management Rules](#file-management-rules)
|
|
19
|
-
- [Workflow Tips](#workflow-tips)
|
|
20
|
-
- [API Reference](#api-reference)
|
|
21
|
-
- [Agent Configuration](#agent-configuration)
|
|
22
|
-
- [Why Single-Source?](#why-single-source)
|
|
23
|
-
- [Quick Start](#quick-start)
|
|
24
|
-
- [Configuration Options](#configuration-options-1)
|
|
25
|
-
- [Built-in Rule Bundles](#built-in-rule-bundles)
|
|
26
|
-
- [Custom Rules](#custom-rules)
|
|
27
|
-
- [Skills](#skills)
|
|
28
|
-
- [Sub-Agents](#sub-agents)
|
|
29
|
-
- [MCP Server Configuration](#mcp-server-configuration)
|
|
30
|
-
- [Platform-Specific Settings](#platform-specific-settings)
|
|
31
|
-
- [Template Variables](#template-variables)
|
|
32
|
-
- [Examples](#examples)
|
|
33
|
-
- [Troubleshooting](#troubleshooting)
|
|
34
|
-
- [Additional Resources](#additional-resources)
|
|
35
|
-
|
|
36
|
-
## Overview
|
|
37
|
-
|
|
38
|
-
This guide explains the core infrastructure tools used in our projects: Projen and Configulator. These tools help us maintain consistency across multiple projects and reduce repetitive setup work.
|
|
39
|
-
|
|
40
|
-
## What is Projen?
|
|
41
|
-
|
|
42
|
-
Projen is a project generator and configuration management tool that:
|
|
43
|
-
|
|
44
|
-
- Creates standardized project structures
|
|
45
|
-
- Manages configuration files programmatically
|
|
46
|
-
- Handles dependency updates automatically
|
|
47
|
-
- Provides consistent build workflows
|
|
48
|
-
|
|
49
|
-
### Key Concepts
|
|
50
|
-
|
|
51
|
-
**Components:** Individual pieces of configuration (e.g., Jest, Vitest, Prettier, TypeScript). Each component configures specific files and settings. When you add or remove a component, all its associated files and configurations are automatically managed.
|
|
52
|
-
|
|
53
|
-
**Project Types:** Base-level configurations for different kinds of projects (e.g., TypeScript app, monorepo, React project).
|
|
54
|
-
|
|
55
|
-
**Synthesis:** The process of generating actual files from your configuration. Run `npx projen` to synthesize your project.
|
|
56
|
-
|
|
57
|
-
## What is Configulator?
|
|
58
|
-
|
|
59
|
-
Configulator is CodeDrifters' custom extension of Projen. It:
|
|
60
|
-
|
|
61
|
-
- Extends standard Projen configurations with our preferred defaults
|
|
62
|
-
- Provides company-specific components and workflows
|
|
63
|
-
- Available as an npm package: `@codedrifters/configulator`
|
|
64
|
-
|
|
65
|
-
### Why We Built It
|
|
66
|
-
|
|
67
|
-
Instead of setting up each new project from scratch (90% identical setup repeated), Configulator lets us:
|
|
68
|
-
|
|
69
|
-
- Generate consistent project structures
|
|
70
|
-
- Pick and choose components we need
|
|
71
|
-
- Maintain standardized tooling across all projects
|
|
72
|
-
- Receive updates to common configurations automatically
|
|
73
|
-
|
|
74
|
-
## Project Types
|
|
75
|
-
|
|
76
|
-
Configulator provides two main project types designed for monorepo workflows:
|
|
77
|
-
|
|
78
|
-
### MonorepoProject
|
|
79
|
-
|
|
80
|
-
**MonorepoProject** extends Projen's `TypeScriptAppProject` and is designed specifically for monorepo root projects. It provides all the infrastructure needed to manage a monorepo with multiple sub-projects.
|
|
81
|
-
|
|
82
|
-
#### When to Use It
|
|
83
|
-
|
|
84
|
-
Use `MonorepoProject` for:
|
|
85
|
-
- Root-level monorepo configuration
|
|
86
|
-
- Managing workspace-wide settings (PNPM, Turborepo, VS Code)
|
|
87
|
-
- Defining shared dependency catalogs
|
|
88
|
-
- Configuring build workflows for the entire monorepo
|
|
89
|
-
|
|
90
|
-
#### Key Features
|
|
91
|
-
|
|
92
|
-
- **PNPM Workspace Management**: Automatically generates and manages `pnpm-workspace.yaml`
|
|
93
|
-
- **Turborepo Integration**: Built-in support for Turborepo with remote caching capabilities
|
|
94
|
-
- **VS Code Configuration**: Automatic VS Code settings for consistent development experience
|
|
95
|
-
- **Default Catalog**: Pre-configured catalog of common dependency versions (AWS CDK, Projen, Constructs, Turbo)
|
|
96
|
-
- **Build Workflow Configuration**: GitHub Actions workflows with Turborepo support
|
|
97
|
-
- **TypeScript Configuration**: Pre-configured TypeScript with sensible defaults
|
|
98
|
-
|
|
99
|
-
#### Basic Example
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
import { MonorepoProject } from '@codedrifters/configulator';
|
|
103
|
-
|
|
104
|
-
const project = new MonorepoProject({
|
|
105
|
-
name: 'my-monorepo'
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
project.synth();
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
#### Advanced Example with Remote Cache
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
import { MonorepoProject } from '@codedrifters/configulator';
|
|
115
|
-
|
|
116
|
-
const project = new MonorepoProject({
|
|
117
|
-
name: 'my-monorepo',
|
|
118
|
-
|
|
119
|
-
turboOptions: {
|
|
120
|
-
remoteCacheOptions: {
|
|
121
|
-
profileName: 'profile-prod-000000000000-us-east-1',
|
|
122
|
-
oidcRole: 'arn:aws:iam::000000000000:role/TurborepoRemoteCachingRole',
|
|
123
|
-
endpointParamName: '/TURBOREPO/ENDPOINT/PARAMETER',
|
|
124
|
-
tokenParamName: '/TURBOREPO/TOKEN/PARAMETER',
|
|
125
|
-
teamName: 'prod',
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
pnpmOptions: {
|
|
130
|
-
pnpmWorkspaceOptions: {
|
|
131
|
-
onlyBuiltDependencies: ['@swc/core', 'esbuild', 'unrs-resolver'],
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
project.synth();
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
#### Configuration Options
|
|
140
|
-
|
|
141
|
-
The `MonorepoProject` accepts all options from `TypeScriptProjectOptions` plus:
|
|
142
|
-
|
|
143
|
-
| Option | Type | Default | Description |
|
|
144
|
-
|--------|------|---------|-------------|
|
|
145
|
-
| `name` | `string` | **Required** | Project name |
|
|
146
|
-
| `turbo` | `boolean` | `true` | Enable Turborepo support |
|
|
147
|
-
| `turboOptions` | `TurboRepoOptions` | `undefined` | Turborepo configuration including remote cache options |
|
|
148
|
-
| `pnpmOptions.version` | `string` | `VERSION.PNPM_VERSION` | PNPM version to use |
|
|
149
|
-
| `pnpmOptions.pnpmWorkspaceOptions` | `PnpmWorkspaceOptions` | See below | PNPM workspace configuration |
|
|
150
|
-
|
|
151
|
-
**Default Behavior:**
|
|
152
|
-
- `projenrcTs: true` - Uses TypeScript for projen configuration
|
|
153
|
-
- `prettier: true` - Enables Prettier formatting
|
|
154
|
-
- `licensed: false` - No license by default
|
|
155
|
-
- `sampleCode: false` - No sample code generated
|
|
156
|
-
- `jest: false` - Jest disabled at root level
|
|
157
|
-
- `release: false` - Root project is not released
|
|
158
|
-
- `depsUpgrade: false` - No automatic dependency upgrades at root
|
|
159
|
-
- `disableTsconfigDev: true` - No tsconfig.dev.json at root
|
|
160
|
-
- `packageManager: NodePackageManager.PNPM` - PNPM is mandatory
|
|
161
|
-
- `defaultReleaseBranch: "main"` - Standard branch name
|
|
162
|
-
|
|
163
|
-
**Pull Request Linting:**
|
|
164
|
-
- By default, pull request titles are validated to follow [Conventional Commits](https://www.conventionalcommits.org/)
|
|
165
|
-
- All conventional commit types are allowed by default: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`
|
|
166
|
-
- This provides flexibility for different types of changes while maintaining consistency
|
|
167
|
-
|
|
168
|
-
**Overriding Pull Request Lint Options:**
|
|
169
|
-
|
|
170
|
-
To customize which commit types are allowed, override the `githubOptions.pullRequestLintOptions`:
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
const project = new MonorepoProject({
|
|
174
|
-
name: 'my-monorepo',
|
|
175
|
-
githubOptions: {
|
|
176
|
-
pullRequestLintOptions: {
|
|
177
|
-
semanticTitleOptions: {
|
|
178
|
-
types: ['feat', 'fix', 'docs', 'chore'], // Only allow these types
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
You can also configure other pull request linting options:
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
const project = new MonorepoProject({
|
|
189
|
-
name: 'my-monorepo',
|
|
190
|
-
githubOptions: {
|
|
191
|
-
pullRequestLintOptions: {
|
|
192
|
-
semanticTitleOptions: {
|
|
193
|
-
types: ['feat', 'fix', 'docs'],
|
|
194
|
-
requireScope: true, // Require scope in commit type (e.g., feat(ui):)
|
|
195
|
-
scopes: ['ui', 'api', 'core'], // Only allow these scopes
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
});
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
The root project automatically includes `@codedrifters/configulator` and `constructs` as dev dependencies.
|
|
203
|
-
|
|
204
|
-
### TypeScriptProject
|
|
205
|
-
|
|
206
|
-
**TypeScriptProject** extends Projen's `TypeScriptProject` with CodeDrifters defaults. It's designed for sub-projects within a monorepo or standalone TypeScript projects.
|
|
207
|
-
|
|
208
|
-
#### When to Use It
|
|
209
|
-
|
|
210
|
-
Use `TypeScriptProject` for:
|
|
211
|
-
- Sub-projects within a monorepo (most common use case)
|
|
212
|
-
- Standalone TypeScript libraries or applications
|
|
213
|
-
- Packages that will be published to NPM
|
|
214
|
-
- Projects that need consistent testing, linting, and build configuration
|
|
215
|
-
|
|
216
|
-
#### Key Features
|
|
217
|
-
|
|
218
|
-
- **Automatic PNPM Version Inheritance**: Inherits PNPM version from parent `MonorepoProject` when used as a sub-project
|
|
219
|
-
- **Configurable Test Runner**: Choose Jest (default) or Vitest via the `testRunner` option. Jest uses `@swc/jest` for fast execution; Vitest uses a generated `vitest.config.ts` with coverage and watch tasks.
|
|
220
|
-
- **Prettier Integration**: Automatic Prettier configuration
|
|
221
|
-
- **Automatic Turborepo Integration**: Automatically configures Turborepo tasks when parent has TurboRepo enabled
|
|
222
|
-
- **Catalog Dependency Support**: Can use catalog dependencies defined in parent workspace
|
|
223
|
-
- **Release Support**: Built-in support for NPM releases with continuous deployment triggers
|
|
224
|
-
|
|
225
|
-
#### Basic Example
|
|
226
|
-
|
|
227
|
-
```typescript
|
|
228
|
-
import { MonorepoProject, TypeScriptProject } from '@codedrifters/configulator';
|
|
229
|
-
|
|
230
|
-
// Root project
|
|
231
|
-
const root = new MonorepoProject({
|
|
232
|
-
name: 'my-monorepo'
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
// Sub-project
|
|
236
|
-
const myPackage = new TypeScriptProject({
|
|
237
|
-
name: 'my-package',
|
|
238
|
-
packageName: '@myorg/my-package',
|
|
239
|
-
outdir: 'packages/my-package',
|
|
240
|
-
parent: root,
|
|
241
|
-
description: 'My awesome package',
|
|
242
|
-
deps: ['some-dependency'],
|
|
243
|
-
devDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
root.synth();
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
#### Example with Release Configuration
|
|
250
|
-
|
|
251
|
-
```typescript
|
|
252
|
-
import { MonorepoProject, TypeScriptProject } from '@codedrifters/configulator';
|
|
253
|
-
|
|
254
|
-
const root = new MonorepoProject({
|
|
255
|
-
name: 'my-monorepo'
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
const constructs = new TypeScriptProject({
|
|
259
|
-
name: '@codedrifters/constructs',
|
|
260
|
-
packageName: '@codedrifters/constructs',
|
|
261
|
-
outdir: 'packages/@codedrifters/constructs',
|
|
262
|
-
description: 'Constructs frequently used in CodeDrifter projects.',
|
|
263
|
-
repository: 'https://github.com/codedrifters/packages',
|
|
264
|
-
authorName: 'CodeDrifters',
|
|
265
|
-
authorOrganization: true,
|
|
266
|
-
licensed: false,
|
|
267
|
-
parent: root,
|
|
268
|
-
|
|
269
|
-
deps: [
|
|
270
|
-
'@aws-sdk/client-dynamodb',
|
|
271
|
-
'@types/aws-lambda',
|
|
272
|
-
'change-case@^4.0',
|
|
273
|
-
'type-fest@^4',
|
|
274
|
-
],
|
|
275
|
-
devDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
|
|
276
|
-
peerDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
|
|
277
|
-
|
|
278
|
-
release: true,
|
|
279
|
-
releaseToNpm: true,
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
root.synth();
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
#### Parent-Child Relationship
|
|
286
|
-
|
|
287
|
-
When `TypeScriptProject` is created with a `parent` that is a `MonorepoProject`:
|
|
288
|
-
|
|
289
|
-
1. **PNPM Version**: Automatically inherits the PNPM version from the parent
|
|
290
|
-
2. **Workspace Integration**: Automatically added to the parent's PNPM workspace
|
|
291
|
-
3. **Turborepo Integration**: If parent has Turborepo enabled, the sub-project automatically gets Turborepo task configuration
|
|
292
|
-
4. **Catalog Dependencies**: Can reference catalog dependencies defined in the parent's workspace
|
|
293
|
-
5. **Dependency Upgrade Exclusions**: Automatically excludes catalog-managed dependencies from upgrade workflows
|
|
294
|
-
|
|
295
|
-
#### Configuration Options
|
|
296
|
-
|
|
297
|
-
The `TypeScriptProject` accepts all options from Projen's `TypeScriptProjectOptions` with these defaults:
|
|
298
|
-
|
|
299
|
-
| Option | Type | Default | Description |
|
|
300
|
-
|--------|------|---------|-------------|
|
|
301
|
-
| `name` | `string` | **Required** | Project name |
|
|
302
|
-
| `packageName` | `string` | Same as `name` | NPM package name |
|
|
303
|
-
| `outdir` | `string` | `"."` | Output directory (required for sub-projects) |
|
|
304
|
-
| `parent` | `MonorepoProject` | `undefined` | Parent monorepo project (recommended) |
|
|
305
|
-
| `defaultReleaseBranch` | `string` | `"main"` | Default release branch |
|
|
306
|
-
| `packageManager` | `NodePackageManager` | `PNPM` | Package manager (always PNPM) |
|
|
307
|
-
| `prettier` | `boolean` | `true` | Enable Prettier |
|
|
308
|
-
| `sampleCode` | `boolean` | `false` | Generate sample code |
|
|
309
|
-
| `release` | `boolean` | `false` | Enable NPM releases |
|
|
310
|
-
| `licensed` | `boolean` | `false` | Include license (unless `license` option provided) |
|
|
311
|
-
| `testRunner` | `TestRunner` | `TestRunner.JEST` | Test runner: `TestRunner.JEST` or `TestRunner.VITEST` |
|
|
312
|
-
| `vitestOptions` | `VitestOptions` | `undefined` | Options for Vitest (only used when `testRunner` is `TestRunner.VITEST`) |
|
|
313
|
-
|
|
314
|
-
**Test runner (Jest or Vitest):**
|
|
315
|
-
- **Jest (default):** External `jest.config.json`, `@swc/jest` for fast compilation, test files in `src/`. Use when you want to keep existing Jest-based workflows.
|
|
316
|
-
- **Vitest:** Set `testRunner: TestRunner.VITEST` to use Vitest. The project gets a generated `vitest.config.ts`, `vitest` (and optionally `@vitest/coverage-v8`) as devDeps, and tasks: `test` (runs `vitest run`), `test:watch`. Snapshots are updated automatically on each test run to match the project's previous Jest behavior (no separate snapshot-update step). Coverage directory is added to `.gitignore` and `.npmignore`. Jest is disabled (`jest: false`) when Vitest is selected; the two cannot be used together.
|
|
317
|
-
|
|
318
|
-
**NPM Ignore:**
|
|
319
|
-
- Automatically ignores `*.spec.*`, `*.test.*`, and `__fixtures__` patterns
|
|
320
|
-
|
|
321
|
-
**Release Configuration:**
|
|
322
|
-
- Uses continuous release trigger
|
|
323
|
-
- Only releases when package directory content changes
|
|
324
|
-
- Release path based on `outdir`
|
|
325
|
-
|
|
326
|
-
## Usage Patterns
|
|
327
|
-
|
|
328
|
-
### Monorepo Setup Pattern
|
|
329
|
-
|
|
330
|
-
The most common pattern is to create a monorepo with a root project and multiple sub-projects:
|
|
331
|
-
|
|
332
|
-
1. **Create the root project** using `MonorepoProject`:
|
|
333
|
-
|
|
334
|
-
```typescript
|
|
335
|
-
// projenrc/root-project.ts
|
|
336
|
-
import { MonorepoProject } from '@codedrifters/configulator';
|
|
337
|
-
|
|
338
|
-
export const configureRootProject = () => {
|
|
339
|
-
const project = new MonorepoProject({
|
|
340
|
-
name: 'my-monorepo',
|
|
341
|
-
turboOptions: {
|
|
342
|
-
remoteCacheOptions: {
|
|
343
|
-
profileName: 'my-profile',
|
|
344
|
-
oidcRole: 'arn:aws:iam::123456789012:role/TurborepoRole',
|
|
345
|
-
endpointParamName: '/TURBOREPO/ENDPOINT',
|
|
346
|
-
tokenParamName: '/TURBOREPO/TOKEN',
|
|
347
|
-
teamName: 'my-team',
|
|
348
|
-
},
|
|
349
|
-
},
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
return project;
|
|
353
|
-
};
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
2. **Add sub-projects** using `TypeScriptProject`:
|
|
357
|
-
|
|
358
|
-
```typescript
|
|
359
|
-
// projenrc/my-package.ts
|
|
360
|
-
import { MonorepoProject } from '@codedrifters/configulator';
|
|
361
|
-
import { TypeScriptProject } from '@codedrifters/configulator';
|
|
362
|
-
|
|
363
|
-
export const configureMyPackage = (parent: MonorepoProject) => {
|
|
364
|
-
const myPackage = new TypeScriptProject({
|
|
365
|
-
name: 'my-package',
|
|
366
|
-
packageName: '@myorg/my-package',
|
|
367
|
-
outdir: 'packages/my-package',
|
|
368
|
-
description: 'My package description',
|
|
369
|
-
parent,
|
|
370
|
-
deps: ['dependency-1', 'dependency-2'],
|
|
371
|
-
devDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
return { myPackage };
|
|
375
|
-
};
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
3. **Wire everything together** in your main projenrc file:
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
// .projenrc.ts or projenrc/index.ts
|
|
382
|
-
import { configureRootProject } from './projenrc/root-project';
|
|
383
|
-
import { configureMyPackage } from './projenrc/my-package';
|
|
384
|
-
|
|
385
|
-
const root = configureRootProject();
|
|
386
|
-
const { myPackage } = configureMyPackage(root);
|
|
387
|
-
|
|
388
|
-
root.synth();
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
### Standalone Project Pattern
|
|
392
|
-
|
|
393
|
-
You can also use `TypeScriptProject` without a parent for standalone projects:
|
|
394
|
-
|
|
395
|
-
```typescript
|
|
396
|
-
import { TypeScriptProject } from '@codedrifters/configulator';
|
|
397
|
-
|
|
398
|
-
const project = new TypeScriptProject({
|
|
399
|
-
name: 'standalone-project',
|
|
400
|
-
packageName: '@myorg/standalone-project',
|
|
401
|
-
description: 'A standalone TypeScript project',
|
|
402
|
-
deps: ['some-dependency'],
|
|
403
|
-
});
|
|
404
|
-
|
|
405
|
-
project.synth();
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
Note: Without a parent, the project will use the default PNPM version from Configulator's version constants.
|
|
409
|
-
|
|
410
|
-
### Dependency Management
|
|
411
|
-
|
|
412
|
-
> **⚠️ Important:** All dependencies must be configured through Projen configuration files (`.projenrc.ts` or `projenrc/*.ts`), never by manually running package manager commands like `npm install`, `pnpm add`, or `yarn add`. Manual installation will create conflicts with Projen-managed files and may be overwritten when you run `npx projen`.
|
|
413
|
-
|
|
414
|
-
#### Using Catalog Dependencies
|
|
415
|
-
|
|
416
|
-
The `MonorepoProject` automatically sets up a default catalog with common dependencies:
|
|
417
|
-
|
|
418
|
-
```typescript
|
|
419
|
-
// Defined in MonorepoProject defaults
|
|
420
|
-
defaultCatalog: {
|
|
421
|
-
'aws-cdk': VERSION.AWS_CDK_CLI_VERSION,
|
|
422
|
-
'aws-cdk-lib': VERSION.AWS_CDK_LIB_VERSION,
|
|
423
|
-
'projen': VERSION.PROJEN_VERSION,
|
|
424
|
-
'constructs': VERSION.AWS_CONSTRUCTS_VERSION,
|
|
425
|
-
'turbo': VERSION.TURBO_VERSION,
|
|
426
|
-
}
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
Sub-projects can reference these using the `catalog:` protocol:
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
const myPackage = new TypeScriptProject({
|
|
433
|
-
// ... other options
|
|
434
|
-
devDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
|
|
435
|
-
peerDeps: ['aws-cdk-lib@catalog:', 'constructs@catalog:'],
|
|
436
|
-
});
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
#### Workspace Dependencies
|
|
440
|
-
|
|
441
|
-
Sub-projects can depend on other packages in the same monorepo:
|
|
442
|
-
|
|
443
|
-
```typescript
|
|
444
|
-
const packageB = new TypeScriptProject({
|
|
445
|
-
// ... other options
|
|
446
|
-
deps: ['@myorg/package-a@workspace:*'],
|
|
447
|
-
});
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
#### Custom Catalog
|
|
451
|
-
|
|
452
|
-
You can also define custom catalogs in the `MonorepoProject`:
|
|
453
|
-
|
|
454
|
-
```typescript
|
|
455
|
-
const root = new MonorepoProject({
|
|
456
|
-
name: 'my-monorepo',
|
|
457
|
-
pnpmOptions: {
|
|
458
|
-
pnpmWorkspaceOptions: {
|
|
459
|
-
defaultCatalog: {
|
|
460
|
-
'react': '^18.0.0',
|
|
461
|
-
'typescript': '^5.0.0',
|
|
462
|
-
},
|
|
463
|
-
namedCatalogs: {
|
|
464
|
-
frontend: {
|
|
465
|
-
'react': '^18.0.0',
|
|
466
|
-
'react-dom': '^18.0.0',
|
|
467
|
-
},
|
|
468
|
-
backend: {
|
|
469
|
-
'express': '^4.18.0',
|
|
470
|
-
},
|
|
471
|
-
},
|
|
472
|
-
},
|
|
473
|
-
},
|
|
474
|
-
});
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
Then reference them in sub-projects:
|
|
478
|
-
|
|
479
|
-
```typescript
|
|
480
|
-
// Default catalog
|
|
481
|
-
deps: ['react@catalog:react']
|
|
482
|
-
|
|
483
|
-
// Named catalog
|
|
484
|
-
deps: ['react@catalog:frontend/react']
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
### Updating VERSION constants
|
|
488
|
-
|
|
489
|
-
The catalog versions (e.g. `VERSION.PROJEN_VERSION`, `VERSION.TURBO_VERSION`) in `src/versions.ts` can be updated automatically so they stay in sync with npm releases while respecting the PNPM workspace `minimumReleaseAge` (so only versions published long enough ago are considered).
|
|
490
|
-
|
|
491
|
-
**What it does**
|
|
492
|
-
|
|
493
|
-
- A script (`scripts/update-versions.ts` at monorepo root) fetches the latest eligible version for each npm-backed constant from the npm registry using the `time` field.
|
|
494
|
-
- Only versions that have been published for at least `minimumReleaseAge` minutes (from the PNPM workspace) are considered.
|
|
495
|
-
- The script runs as part of the **upgrade** task, so when the upgrade workflow runs (e.g. nightly or `workflow_dispatch`), version updates are included in the same PR as dependency upgrades.
|
|
496
|
-
|
|
497
|
-
**How to run**
|
|
498
|
-
|
|
499
|
-
From the monorepo root:
|
|
500
|
-
|
|
501
|
-
- **Propose only** (print suggested changes, do not edit files):
|
|
502
|
-
```bash
|
|
503
|
-
pnpm run update-versions
|
|
504
|
-
```
|
|
505
|
-
- **Apply locally** (update `versions.ts` and run `npx projen`):
|
|
506
|
-
```bash
|
|
507
|
-
pnpm run update-versions -- --apply
|
|
508
|
-
```
|
|
509
|
-
- **In CI**: When run from the upgrade workflow, the script auto-applies when there are updates so changes are included in the upgrade PR.
|
|
510
|
-
|
|
511
|
-
**Adding a new npm-backed constant**
|
|
512
|
-
|
|
513
|
-
1. Add the constant to `src/versions.ts` (e.g. `MY_PACKAGE_VERSION: "1.0.0"`).
|
|
514
|
-
2. Add an entry to `VERSION_NPM_PACKAGES` in `src/version-package-map.ts`:
|
|
515
|
-
```typescript
|
|
516
|
-
{ key: "MY_PACKAGE_VERSION", npmPackage: "my-package" },
|
|
517
|
-
```
|
|
518
|
-
Constants not listed in `VERSION_NPM_PACKAGES` (e.g. `NODE_WORKFLOWS`) are skipped by the update script.
|
|
519
|
-
|
|
520
|
-
### Turborepo Integration
|
|
521
|
-
|
|
522
|
-
When you create a `MonorepoProject` with `turbo: true` (the default), Turborepo is automatically configured. Sub-projects created with `TypeScriptProject` automatically get Turborepo task configuration if their parent has Turborepo enabled.
|
|
523
|
-
|
|
524
|
-
The integration includes:
|
|
525
|
-
- Automatic task definitions (compile, test, package)
|
|
526
|
-
- Output directory configuration (`dist/**`, `lib/**`)
|
|
527
|
-
- Remote cache support (when configured)
|
|
528
|
-
- Build workflow integration
|
|
529
|
-
|
|
530
|
-
See the [Turbo Repo](#turbo-repo) section for more details.
|
|
531
|
-
|
|
532
|
-
## Configuration Options
|
|
533
|
-
|
|
534
|
-
### MonorepoProjectOptions
|
|
535
|
-
|
|
536
|
-
Extends `TypeScriptProjectOptions` with:
|
|
537
|
-
|
|
538
|
-
```typescript
|
|
539
|
-
interface MonorepoProjectOptions {
|
|
540
|
-
name: string; // Required
|
|
541
|
-
turbo?: boolean; // Default: true
|
|
542
|
-
turboOptions?: TurboRepoOptions;
|
|
543
|
-
pnpmOptions?: {
|
|
544
|
-
version?: string;
|
|
545
|
-
pnpmWorkspaceOptions?: PnpmWorkspaceOptions;
|
|
546
|
-
};
|
|
547
|
-
// ... all TypeScriptProjectOptions
|
|
548
|
-
}
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
### TypeScriptProjectOptions
|
|
552
|
-
|
|
553
|
-
Extends Projen's `TypeScriptProjectOptions` with CodeDrifters defaults. See the [TypeScriptProject](#typescriptproject) section for details.
|
|
554
|
-
|
|
555
|
-
### TurboRepoOptions
|
|
556
|
-
|
|
557
|
-
```typescript
|
|
558
|
-
interface TurboRepoOptions {
|
|
559
|
-
turboVersion?: string;
|
|
560
|
-
remoteCacheOptions?: RemoteCacheOptions;
|
|
561
|
-
extends?: Array<string>;
|
|
562
|
-
globalDependencies?: Array<string>;
|
|
563
|
-
globalEnv?: Array<string>;
|
|
564
|
-
globalPassThroughEnv?: Array<string>;
|
|
565
|
-
ui?: 'tui' | 'stream';
|
|
566
|
-
envMode?: string;
|
|
567
|
-
// ... and more
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
interface RemoteCacheOptions {
|
|
571
|
-
profileName: string;
|
|
572
|
-
oidcRole: string;
|
|
573
|
-
endpointParamName: string;
|
|
574
|
-
tokenParamName: string;
|
|
575
|
-
teamName: string;
|
|
576
|
-
}
|
|
577
|
-
```
|
|
578
|
-
|
|
579
|
-
### PnpmWorkspaceOptions
|
|
580
|
-
|
|
581
|
-
```typescript
|
|
582
|
-
interface PnpmWorkspaceOptions {
|
|
583
|
-
fileName?: string; // Default: 'pnpm-workspace.yaml'
|
|
584
|
-
minimumReleaseAge?: number; // Minutes, default: ONE_DAY (1440)
|
|
585
|
-
minimumReleaseAgeExclude?: Array<string>; // Default: ['@codedrifters/*']
|
|
586
|
-
onlyBuiltDependencies?: Array<string>;
|
|
587
|
-
ignoredBuiltDependencies?: Array<string>;
|
|
588
|
-
subprojects?: Array<string>;
|
|
589
|
-
defaultCatalog?: { [key: string]: string };
|
|
590
|
-
namedCatalogs?: { [catalogName: string]: { [dependencyName: string]: string } };
|
|
591
|
-
}
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
## Turbo Repo
|
|
595
|
-
|
|
596
|
-
### What It Does
|
|
597
|
-
|
|
598
|
-
Turbo Repo is a build system for monorepos that:
|
|
599
|
-
|
|
600
|
-
- Caches build outputs intelligently
|
|
601
|
-
- Only rebuilds what changed
|
|
602
|
-
- Speeds up CI/CD significantly
|
|
603
|
-
- Works with remote caching
|
|
604
|
-
|
|
605
|
-
### How It Works
|
|
606
|
-
|
|
607
|
-
**Hashing:** All input files (source code, configs) are hashed
|
|
608
|
-
|
|
609
|
-
**Cache Check:** If inputs haven't changed, cached outputs are reused
|
|
610
|
-
|
|
611
|
-
**Smart Rebuilds:** Only affected packages rebuild when dependencies change
|
|
612
|
-
|
|
613
|
-
**Remote Cache:** Build outputs stored in S3 (not Vercel) for team sharing
|
|
614
|
-
|
|
615
|
-
### Configuration
|
|
616
|
-
|
|
617
|
-
Turborepo is automatically enabled in `MonorepoProject` (can be disabled with `turbo: false`). Configure it using the `turboOptions`:
|
|
618
|
-
|
|
619
|
-
```typescript
|
|
620
|
-
const project = new MonorepoProject({
|
|
621
|
-
name: 'my-monorepo',
|
|
622
|
-
turboOptions: {
|
|
623
|
-
remoteCacheOptions: {
|
|
624
|
-
profileName: 'my-profile',
|
|
625
|
-
oidcRole: 'arn:aws:iam::123456789012:role/TurborepoRole',
|
|
626
|
-
endpointParamName: '/TURBOREPO/ENDPOINT',
|
|
627
|
-
tokenParamName: '/TURBOREPO/TOKEN',
|
|
628
|
-
teamName: 'my-team',
|
|
629
|
-
},
|
|
630
|
-
},
|
|
631
|
-
});
|
|
632
|
-
```
|
|
633
|
-
|
|
634
|
-
### Running Locally
|
|
635
|
-
|
|
636
|
-
Before using Turbo Repo locally, you need AWS credentials:
|
|
637
|
-
|
|
638
|
-
```bash
|
|
639
|
-
# Run the login script (credentials last ~8 hours)
|
|
640
|
-
./scripts/aws-profile-turbo-repo.sh
|
|
641
|
-
```
|
|
642
|
-
|
|
643
|
-
**Common Error:** If you get a "gRPC error" when running Turbo first thing in the morning, the Lambda function is cold. Just run the command again - it will work the second time.
|
|
644
|
-
|
|
645
|
-
### Benefits
|
|
646
|
-
|
|
647
|
-
- **Fast CI:** Builds can complete in under a minute when using cached outputs
|
|
648
|
-
- **Selective Rebuilds:** Only changed code rebuilds, not the entire monorepo
|
|
649
|
-
- **Local + CI Sharing:** Cache between your machine and GitHub Actions
|
|
650
|
-
|
|
651
|
-
## PNPM Workspace
|
|
652
|
-
|
|
653
|
-
The `MonorepoProject` automatically generates and manages `pnpm-workspace.yaml`. This file:
|
|
654
|
-
|
|
655
|
-
- Lists all sub-projects in the `packages` array
|
|
656
|
-
- Configures PNPM settings like `minimumReleaseAge` and `onlyBuiltDependencies`
|
|
657
|
-
- Defines dependency catalogs for version management
|
|
658
|
-
|
|
659
|
-
### Workspace Structure
|
|
660
|
-
|
|
661
|
-
The workspace file is auto-generated and lists all sub-projects:
|
|
662
|
-
|
|
663
|
-
```yaml
|
|
664
|
-
packages:
|
|
665
|
-
- 'packages/package-a'
|
|
666
|
-
- 'packages/package-b'
|
|
667
|
-
- 'apps/frontend'
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
Sub-projects are automatically discovered from `project.subprojects` and any additional paths specified in `pnpmWorkspaceOptions.subprojects`.
|
|
671
|
-
|
|
672
|
-
### Configuration
|
|
673
|
-
|
|
674
|
-
Configure the workspace through `pnpmOptions.pnpmWorkspaceOptions`:
|
|
675
|
-
|
|
676
|
-
```typescript
|
|
677
|
-
const project = new MonorepoProject({
|
|
678
|
-
name: 'my-monorepo',
|
|
679
|
-
pnpmOptions: {
|
|
680
|
-
pnpmWorkspaceOptions: {
|
|
681
|
-
minimumReleaseAge: MINIMUM_RELEASE_AGE.ONE_DAY,
|
|
682
|
-
minimumReleaseAgeExclude: ['@codedrifters/*'],
|
|
683
|
-
onlyBuiltDependencies: ['@swc/core', 'esbuild'],
|
|
684
|
-
defaultCatalog: {
|
|
685
|
-
'react': '^18.0.0',
|
|
686
|
-
},
|
|
687
|
-
},
|
|
688
|
-
},
|
|
689
|
-
});
|
|
690
|
-
```
|
|
691
|
-
|
|
692
|
-
## File Management Rules
|
|
693
|
-
|
|
694
|
-
### DO NOT Edit These Files Directly
|
|
695
|
-
|
|
696
|
-
Projen manages many files automatically. Never edit these files by hand:
|
|
697
|
-
|
|
698
|
-
- Configuration files (`.prettierrc`, `tsconfig.json`, etc.)
|
|
699
|
-
- GitHub workflows (`.github/workflows/*`)
|
|
700
|
-
- Build scripts
|
|
701
|
-
- Most files listed in `.projen/files.json`
|
|
702
|
-
|
|
703
|
-
### Exception: package.json
|
|
704
|
-
|
|
705
|
-
`package.json` is special - Projen reads, modifies, and writes it back, preserving some manual changes. However, you should still manage dependencies through Projen config, not by editing `package.json` directly.
|
|
706
|
-
|
|
707
|
-
### Adding Dependencies
|
|
708
|
-
|
|
709
|
-
**WRONG:**
|
|
710
|
-
```bash
|
|
711
|
-
npm install some-package
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
**CORRECT:** Add dependencies in your `.projenrc.ts` configuration and run `npx projen`.
|
|
715
|
-
|
|
716
|
-
```typescript
|
|
717
|
-
const project = new TypeScriptProject({
|
|
718
|
-
// ... other options
|
|
719
|
-
deps: ['some-package'],
|
|
720
|
-
});
|
|
721
|
-
```
|
|
722
|
-
|
|
723
|
-
## Workflow Tips
|
|
724
|
-
|
|
725
|
-
### Before Committing
|
|
726
|
-
|
|
727
|
-
Run Turbo build locally (from monorepo root) to cache everything:
|
|
728
|
-
|
|
729
|
-
```bash
|
|
730
|
-
# This caches outputs that GitHub Actions can reuse
|
|
731
|
-
pnpm build:all
|
|
732
|
-
```
|
|
733
|
-
|
|
734
|
-
Then commit and push. Your GitHub build will be much faster.
|
|
735
|
-
|
|
736
|
-
### Adding New Packages
|
|
737
|
-
|
|
738
|
-
1. Create a new configuration file in `projenrc/` (e.g., `projenrc/new-package.ts`)
|
|
739
|
-
2. Export a function that creates a `TypeScriptProject` with the parent as a parameter
|
|
740
|
-
3. Import and call it in your main projenrc file
|
|
741
|
-
4. Run `npx projen` to regenerate configs
|
|
742
|
-
5. Commit the changes
|
|
743
|
-
|
|
744
|
-
Example:
|
|
745
|
-
|
|
746
|
-
```typescript
|
|
747
|
-
// projenrc/new-package.ts
|
|
748
|
-
import { MonorepoProject, TypeScriptProject } from '@codedrifters/configulator';
|
|
749
|
-
|
|
750
|
-
export const configureNewPackage = (parent: MonorepoProject) => {
|
|
751
|
-
return new TypeScriptProject({
|
|
752
|
-
name: 'new-package',
|
|
753
|
-
packageName: '@myorg/new-package',
|
|
754
|
-
outdir: 'packages/new-package',
|
|
755
|
-
parent,
|
|
756
|
-
deps: ['dependency'],
|
|
757
|
-
});
|
|
758
|
-
};
|
|
759
|
-
```
|
|
760
|
-
|
|
761
|
-
### Updating Configulator
|
|
762
|
-
|
|
763
|
-
To receive updates from Configulator in your project:
|
|
764
|
-
|
|
765
|
-
1. Update the version in your projenrc definition file
|
|
766
|
-
2. Run `npx projen`
|
|
767
|
-
3. Review and test changes
|
|
768
|
-
4. Commit
|
|
769
|
-
|
|
770
|
-
## API Reference
|
|
771
|
-
|
|
772
|
-
### MonorepoProject
|
|
773
|
-
|
|
774
|
-
**Constructor:**
|
|
775
|
-
```typescript
|
|
776
|
-
new MonorepoProject(options: MonorepoProjectOptions)
|
|
777
|
-
```
|
|
778
|
-
|
|
779
|
-
**Key Properties:**
|
|
780
|
-
- `pnpmVersion: string` - The PNPM version used by the monorepo
|
|
781
|
-
|
|
782
|
-
**Key Methods:**
|
|
783
|
-
- Inherits all methods from `TypeScriptAppProject`
|
|
784
|
-
|
|
785
|
-
### TypeScriptProject
|
|
786
|
-
|
|
787
|
-
**Constructor:**
|
|
788
|
-
```typescript
|
|
789
|
-
new TypeScriptProject(options: TypeScriptProjectOptions)
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
**Key Methods:**
|
|
793
|
-
- `addDeps(...deps: string[])` - Add runtime dependencies
|
|
794
|
-
- `addDevDeps(...deps: string[])` - Add dev dependencies
|
|
795
|
-
- `addPeerDeps(...deps: string[])` - Add peer dependencies
|
|
796
|
-
- Inherits all methods from Projen's `TypeScriptProject`
|
|
797
|
-
|
|
798
|
-
### PnpmWorkspace
|
|
799
|
-
|
|
800
|
-
**Static Method:**
|
|
801
|
-
```typescript
|
|
802
|
-
PnpmWorkspace.of(project: Project): PnpmWorkspace | undefined
|
|
803
|
-
```
|
|
804
|
-
|
|
805
|
-
Returns the PnpmWorkspace component from a project if it exists.
|
|
806
|
-
|
|
807
|
-
### TurboRepo
|
|
808
|
-
|
|
809
|
-
**Static Method:**
|
|
810
|
-
```typescript
|
|
811
|
-
TurboRepo.of(project: Project): TurboRepo | undefined
|
|
812
|
-
```
|
|
813
|
-
|
|
814
|
-
Returns the TurboRepo component from a project if it exists.
|
|
815
|
-
|
|
816
|
-
### AgentConfig
|
|
817
|
-
|
|
818
|
-
**Static Method:**
|
|
819
|
-
```typescript
|
|
820
|
-
AgentConfig.of(project: Project): AgentConfig | undefined
|
|
821
|
-
```
|
|
822
|
-
|
|
823
|
-
Returns the AgentConfig component from a project if it exists.
|
|
824
|
-
|
|
825
|
-
## Agent Configuration
|
|
826
|
-
|
|
827
|
-
AgentConfig provides a **single-source, multi-platform** approach to AI coding assistant configuration. Define rules, skills, sub-agents, and MCP servers once in your `.projenrc.ts`, and configulator renders the correct files for each target platform during synthesis.
|
|
828
|
-
|
|
829
|
-
### Why Single-Source?
|
|
830
|
-
|
|
831
|
-
Every AI coding assistant has its own configuration format — Cursor uses `.mdc` files with YAML frontmatter, Claude Code uses `.md` files and `settings.json`, Codex uses `AGENTS.md`, and Copilot uses `.github/instructions/`. Without a unified approach, teams end up maintaining duplicate rule sets that inevitably drift out of sync.
|
|
832
|
-
|
|
833
|
-
AgentConfig solves this by defining rules in a platform-agnostic format and rendering them into each platform's native format:
|
|
834
|
-
|
|
835
|
-
```
|
|
836
|
-
.projenrc.ts (AgentConfig)
|
|
837
|
-
│
|
|
838
|
-
├── Cursor: .cursor/rules/*.mdc, .cursor/agents/*.md, .cursor/mcp.json
|
|
839
|
-
├── Claude: CLAUDE.md, .claude/rules/*.md, .claude/settings.json, .claude/skills/*, .claude/agents/*
|
|
840
|
-
├── Codex: AGENTS.md (planned)
|
|
841
|
-
└── Copilot: .github/instructions/*.md (planned)
|
|
842
|
-
```
|
|
843
|
-
|
|
844
|
-
### Quick Start
|
|
845
|
-
|
|
846
|
-
Enable agent configuration with defaults — auto-detects rule bundles based on your project's tooling:
|
|
847
|
-
|
|
848
|
-
```typescript
|
|
849
|
-
// In .projenrc.ts — MonorepoProject
|
|
850
|
-
const project = new MonorepoProject({
|
|
851
|
-
name: "my-project",
|
|
852
|
-
agentConfig: true, // or {} for defaults
|
|
853
|
-
});
|
|
854
|
-
|
|
855
|
-
// Sub-projects inherit from parent automatically
|
|
856
|
-
const api = new TypeScriptProject({
|
|
857
|
-
parent: project,
|
|
858
|
-
name: "@my-org/api",
|
|
859
|
-
outdir: "packages/api",
|
|
860
|
-
// agentConfig inherited from parent — no explicit config needed
|
|
861
|
-
});
|
|
862
|
-
```
|
|
863
|
-
|
|
864
|
-
After running `npx projen`, the following files are generated (varies by detected tooling):
|
|
865
|
-
|
|
866
|
-
| Platform | Files |
|
|
867
|
-
|----------|-------|
|
|
868
|
-
| Cursor | `.cursor/rules/*.mdc`, `.cursor/agents/*.md`, `.cursor/mcp.json`, `.cursor/hooks.json`, `.cursorignore`, `.cursorindexingignore` |
|
|
869
|
-
| Claude | `CLAUDE.md`, `.claude/rules/*.md`, `.claude/settings.json`, `.claude/skills/*/SKILL.md`, `.claude/agents/*.md` |
|
|
870
|
-
| Codex | `AGENTS.md` (planned) |
|
|
871
|
-
| Copilot | `.github/instructions/*.md` (planned) |
|
|
872
|
-
|
|
873
|
-
### Configuration Options
|
|
874
|
-
|
|
875
|
-
The `AgentConfigOptions` interface controls all aspects of agent configuration:
|
|
876
|
-
|
|
877
|
-
| Option | Type | Default | Description |
|
|
878
|
-
|--------|------|---------|-------------|
|
|
879
|
-
| `platforms` | `AgentPlatform[]` | `[CURSOR, CLAUDE]` | Target platforms to generate config for |
|
|
880
|
-
| `autoDetectBundles` | `boolean` | `true` | Auto-detect rule bundles based on project tooling |
|
|
881
|
-
| `includeBundles` | `string[]` | — | Force-include specific bundles by name |
|
|
882
|
-
| `excludeBundles` | `string[]` | — | Exclude bundles even if auto-detected |
|
|
883
|
-
| `includeBaseRules` | `boolean` | `true` | Include base rules (project-overview, conventions) |
|
|
884
|
-
| `excludeRules` | `string[]` | — | Exclude individual rules by name |
|
|
885
|
-
| `ruleExtensions` | `Record<string, string>` | — | Append content to existing rules |
|
|
886
|
-
| `rules` | `AgentRule[]` | — | Custom rules (override bundled rules of same name) |
|
|
887
|
-
| `skills` | `AgentSkill[]` | — | Custom skill definitions |
|
|
888
|
-
| `subAgents` | `AgentSubAgent[]` | — | Custom sub-agent definitions |
|
|
889
|
-
| `mcpServers` | `Record<string, McpServerConfig>` | — | MCP server configs (cross-platform) |
|
|
890
|
-
| `claudeSettings` | `ClaudeSettingsConfig` | — | Claude Code settings.json config |
|
|
891
|
-
| `cursorSettings` | `CursorSettingsConfig` | — | Cursor hooks and ignore patterns |
|
|
892
|
-
|
|
893
|
-
### Built-in Rule Bundles
|
|
894
|
-
|
|
895
|
-
Configulator ships with context-aware rule bundles that are automatically included when their tooling is detected in the project:
|
|
896
|
-
|
|
897
|
-
| Bundle | Auto-detection | Rules | Description |
|
|
898
|
-
|--------|---------------|-------|-------------|
|
|
899
|
-
| `base` | Always (unless `includeBaseRules: false`) | `project-overview`, `interaction-style`, `general-conventions`, `pull-request-conventions`, `branch-naming-conventions`, `issue-conventions` | Core project context, interaction style, and coding conventions. Also includes `create-rule` and `review-pr` skills. |
|
|
900
|
-
| `typescript` | `tsconfig.json` exists | `typescript-conventions` | Type safety, naming, JSDoc, member ordering |
|
|
901
|
-
| `vitest` | Vitest component present | `vitest-testing` | Vitest testing patterns and file scoping |
|
|
902
|
-
| `jest` | `jest` in dependencies | `jest-testing` | Jest testing patterns, SWC compilation, mocking |
|
|
903
|
-
| `turborepo` | TurboRepo component present | `turborepo-conventions` | Build system, task pipeline, caching |
|
|
904
|
-
| `pnpm` | PnpmWorkspace component present | `pnpm-workspace` | Workspace dependencies, package management |
|
|
905
|
-
| `aws-cdk` | `aws-cdk-lib` in dependencies | `aws-cdk-conventions` | Construct patterns, L2/L3, IAM best practices |
|
|
906
|
-
| `projen` | `projen` in dependencies | `projen-conventions` | Config patterns, synthesis workflow, components |
|
|
907
|
-
|
|
908
|
-
**Controlling bundles:**
|
|
909
|
-
|
|
910
|
-
```typescript
|
|
911
|
-
new AgentConfig(project, {
|
|
912
|
-
// Disable auto-detection entirely
|
|
913
|
-
autoDetectBundles: false,
|
|
914
|
-
|
|
915
|
-
// Force-include bundles that aren't auto-detected
|
|
916
|
-
includeBundles: ["aws-cdk"],
|
|
917
|
-
|
|
918
|
-
// Exclude auto-detected bundles
|
|
919
|
-
excludeBundles: ["jest"],
|
|
920
|
-
|
|
921
|
-
// Disable the base rule set
|
|
922
|
-
includeBaseRules: false,
|
|
923
|
-
|
|
924
|
-
// Exclude individual rules from any source
|
|
925
|
-
excludeRules: ["branch-naming-conventions"],
|
|
926
|
-
|
|
927
|
-
// Append content to an existing rule without replacing it
|
|
928
|
-
ruleExtensions: {
|
|
929
|
-
"typescript-conventions": "## Additional Conventions\n\n- Use branded types for IDs",
|
|
930
|
-
},
|
|
931
|
-
});
|
|
932
|
-
```
|
|
933
|
-
|
|
934
|
-
### Custom Rules
|
|
935
|
-
|
|
936
|
-
Define custom rules using the `AgentRule` interface:
|
|
937
|
-
|
|
938
|
-
```typescript
|
|
939
|
-
import { AGENT_RULE_SCOPE, CLAUDE_RULE_TARGET } from "@codedrifters/configulator";
|
|
940
|
-
|
|
941
|
-
new AgentConfig(project, {
|
|
942
|
-
rules: [
|
|
943
|
-
{
|
|
944
|
-
name: "api-conventions",
|
|
945
|
-
description: "REST API design conventions for this project",
|
|
946
|
-
scope: AGENT_RULE_SCOPE.FILE_PATTERN,
|
|
947
|
-
filePatterns: ["src/api/**/*.ts", "src/routes/**/*.ts"],
|
|
948
|
-
content: `# API Conventions
|
|
949
|
-
|
|
950
|
-
- Use RESTful resource naming
|
|
951
|
-
- Always validate request bodies with Zod
|
|
952
|
-
- Return consistent error response shapes`,
|
|
953
|
-
tags: ["api"],
|
|
954
|
-
},
|
|
955
|
-
],
|
|
956
|
-
});
|
|
957
|
-
```
|
|
958
|
-
|
|
959
|
-
**Rule fields:**
|
|
960
|
-
|
|
961
|
-
| Field | Type | Required | Description |
|
|
962
|
-
|-------|------|----------|-------------|
|
|
963
|
-
| `name` | `string` | Yes | Unique kebab-case identifier, used as filename |
|
|
964
|
-
| `description` | `string` | Yes | AI-readable purpose (Cursor uses this for rule selection) |
|
|
965
|
-
| `scope` | `AgentRuleScope` | Yes | `ALWAYS` (always active) or `FILE_PATTERN` (active on matching files) |
|
|
966
|
-
| `filePatterns` | `string[]` | When `FILE_PATTERN` | Glob patterns for conditional activation |
|
|
967
|
-
| `content` | `string` | Yes | Markdown rule body |
|
|
968
|
-
| `platforms` | `AgentPlatformOverrides` | No | Per-platform overrides |
|
|
969
|
-
| `tags` | `string[]` | No | For categorizing and ordering rules |
|
|
970
|
-
|
|
971
|
-
**Platform overrides** let you customize or exclude rules per platform:
|
|
972
|
-
|
|
973
|
-
```typescript
|
|
974
|
-
{
|
|
975
|
-
name: "claude-specific-rule",
|
|
976
|
-
description: "A rule only for Claude Code",
|
|
977
|
-
scope: AGENT_RULE_SCOPE.ALWAYS,
|
|
978
|
-
content: "# Claude-Only\n\nThis rule is excluded from Cursor.",
|
|
979
|
-
platforms: {
|
|
980
|
-
cursor: { exclude: true },
|
|
981
|
-
claude: { target: CLAUDE_RULE_TARGET.CLAUDE_MD }, // Render to CLAUDE.md instead of .claude/rules/
|
|
982
|
-
},
|
|
983
|
-
}
|
|
984
|
-
```
|
|
985
|
-
|
|
986
|
-
Claude supports three render targets:
|
|
987
|
-
- `SCOPED_FILE` (default) — `.claude/rules/{name}.md` with optional paths frontmatter
|
|
988
|
-
- `AGENTS_MD` — `AGENTS.md` (always-active, shared with Codex)
|
|
989
|
-
- `CLAUDE_MD` — `CLAUDE.md` (always-active, Claude-only)
|
|
990
|
-
|
|
991
|
-
### Skills
|
|
992
|
-
|
|
993
|
-
Skills define slash commands and automated workflows. They are rendered to `.claude/skills/*/SKILL.md` (Claude Code) and `.cursor/skills/` (Cursor).
|
|
994
|
-
|
|
995
|
-
```typescript
|
|
996
|
-
new AgentConfig(project, {
|
|
997
|
-
skills: [
|
|
998
|
-
{
|
|
999
|
-
name: "deploy-check",
|
|
1000
|
-
description: "Verify deployment readiness before merging",
|
|
1001
|
-
instructions: `# Deploy Check
|
|
1002
|
-
|
|
1003
|
-
1. Run the full test suite
|
|
1004
|
-
2. Check for any TODO/FIXME comments in changed files
|
|
1005
|
-
3. Verify no console.log statements in production code
|
|
1006
|
-
4. Report findings`,
|
|
1007
|
-
allowedTools: ["Read", "Glob", "Grep", "Bash(pnpm run test *)"],
|
|
1008
|
-
disableModelInvocation: true, // Only triggered by /deploy-check
|
|
1009
|
-
},
|
|
1010
|
-
],
|
|
1011
|
-
});
|
|
1012
|
-
```
|
|
1013
|
-
|
|
1014
|
-
**Skill fields:**
|
|
1015
|
-
|
|
1016
|
-
| Field | Type | Default | Description |
|
|
1017
|
-
|-------|------|---------|-------------|
|
|
1018
|
-
| `name` | `string` | — | Slash-command name (e.g., `/commit`) |
|
|
1019
|
-
| `description` | `string` | — | Used by AI for auto-invocation decisions |
|
|
1020
|
-
| `instructions` | `string` | — | Markdown body (becomes SKILL.md) |
|
|
1021
|
-
| `allowedTools` | `string[]` | All | Tool allowlist |
|
|
1022
|
-
| `disableModelInvocation` | `boolean` | `false` | Prevent auto-invocation |
|
|
1023
|
-
| `userInvocable` | `boolean` | `true` | Allow `/skill-name` command |
|
|
1024
|
-
| `model` | `string` | — | Model override |
|
|
1025
|
-
| `effort` | `string` | — | Reasoning effort level |
|
|
1026
|
-
| `paths` | `string[]` | — | Auto-load on matching files |
|
|
1027
|
-
| `context` | `string` | — | Set to `'fork'` for isolated subagent |
|
|
1028
|
-
| `agent` | `string` | — | Subagent name when context is `'fork'` |
|
|
1029
|
-
|
|
1030
|
-
**Built-in skills** (from the base bundle):
|
|
1031
|
-
- `create-rule` — Guide for creating new agent rules
|
|
1032
|
-
- `review-pr` — PR review workflow
|
|
1033
|
-
|
|
1034
|
-
### Sub-Agents
|
|
1035
|
-
|
|
1036
|
-
Sub-agents define specialized AI agents that the parent agent can delegate to:
|
|
1037
|
-
|
|
1038
|
-
```typescript
|
|
1039
|
-
import { AGENT_MODEL } from "@codedrifters/configulator";
|
|
1040
|
-
|
|
1041
|
-
new AgentConfig(project, {
|
|
1042
|
-
subAgents: [
|
|
1043
|
-
{
|
|
1044
|
-
name: "test-writer",
|
|
1045
|
-
description: "Write and update unit tests for changed code",
|
|
1046
|
-
prompt: `# Test Writer
|
|
1047
|
-
|
|
1048
|
-
You are a specialized testing agent. Given source files, write comprehensive
|
|
1049
|
-
unit tests following the project's testing conventions.
|
|
1050
|
-
|
|
1051
|
-
- Use the project's test runner (Vitest or Jest)
|
|
1052
|
-
- Follow existing test patterns in the codebase
|
|
1053
|
-
- Ensure full branch coverage`,
|
|
1054
|
-
model: AGENT_MODEL.BALANCED,
|
|
1055
|
-
tools: ["Read", "Glob", "Grep", "Edit", "Write", "Bash(pnpm run test *)"],
|
|
1056
|
-
maxTurns: 20,
|
|
1057
|
-
},
|
|
1058
|
-
],
|
|
1059
|
-
});
|
|
1060
|
-
```
|
|
1061
|
-
|
|
1062
|
-
**Sub-agent fields:**
|
|
1063
|
-
|
|
1064
|
-
| Field | Type | Default | Description |
|
|
1065
|
-
|-------|------|---------|-------------|
|
|
1066
|
-
| `name` | `string` | — | Lowercase kebab-case identifier |
|
|
1067
|
-
| `description` | `string` | — | When to delegate to this agent |
|
|
1068
|
-
| `prompt` | `string` | — | System prompt (markdown) |
|
|
1069
|
-
| `model` | `AgentModel` | `INHERIT` | `INHERIT`, `FAST`, `BALANCED`, or `POWERFUL` |
|
|
1070
|
-
| `tools` | `string[]` | All | Tool allowlist |
|
|
1071
|
-
| `disallowedTools` | `string[]` | — | Tool denylist |
|
|
1072
|
-
| `maxTurns` | `number` | — | Agentic turn limit |
|
|
1073
|
-
| `skills` | `string[]` | — | Pre-loaded skills |
|
|
1074
|
-
| `mcpServers` | `Record<string, McpServerConfig>` | — | MCP servers for this agent |
|
|
1075
|
-
| `canDelegateToAgents` | `string[]` | — | Agents this agent can invoke |
|
|
1076
|
-
| `platforms` | `AgentSubAgentPlatformOverrides` | — | Per-platform overrides |
|
|
1077
|
-
|
|
1078
|
-
**Platform-specific sub-agent overrides:**
|
|
1079
|
-
|
|
1080
|
-
```typescript
|
|
1081
|
-
{
|
|
1082
|
-
name: "code-reviewer",
|
|
1083
|
-
description: "Review code for quality and conventions",
|
|
1084
|
-
prompt: "...",
|
|
1085
|
-
platforms: {
|
|
1086
|
-
claude: {
|
|
1087
|
-
permissionMode: "plan", // default, acceptEdits, dontAsk, bypassPermissions, plan
|
|
1088
|
-
isolation: "worktree", // Run in isolated git worktree
|
|
1089
|
-
background: true, // Run as background task
|
|
1090
|
-
effort: "high", // Reasoning effort: low, medium, high, max
|
|
1091
|
-
},
|
|
1092
|
-
cursor: {
|
|
1093
|
-
readonly: true, // Read-only operations only
|
|
1094
|
-
isBackground: true, // Async background task
|
|
1095
|
-
},
|
|
1096
|
-
},
|
|
1097
|
-
}
|
|
1098
|
-
```
|
|
1099
|
-
|
|
1100
|
-
### MCP Server Configuration
|
|
1101
|
-
|
|
1102
|
-
MCP servers are defined once and rendered to the appropriate config for each platform (`.claude/settings.json` for Claude, `.cursor/mcp.json` for Cursor):
|
|
1103
|
-
|
|
1104
|
-
```typescript
|
|
1105
|
-
import { MCP_TRANSPORT } from "@codedrifters/configulator";
|
|
1106
|
-
|
|
1107
|
-
new AgentConfig(project, {
|
|
1108
|
-
mcpServers: {
|
|
1109
|
-
"my-server": {
|
|
1110
|
-
command: "npx",
|
|
1111
|
-
args: ["-y", "@my-org/mcp-server"],
|
|
1112
|
-
env: { API_KEY: "${API_KEY}" },
|
|
1113
|
-
enabledTools: ["search", "read_file"],
|
|
1114
|
-
},
|
|
1115
|
-
"remote-api": {
|
|
1116
|
-
transport: MCP_TRANSPORT.HTTP,
|
|
1117
|
-
url: "https://api.example.com/mcp",
|
|
1118
|
-
headers: { Authorization: "Bearer ${TOKEN}" },
|
|
1119
|
-
disabledTools: ["dangerous_action"],
|
|
1120
|
-
},
|
|
1121
|
-
},
|
|
1122
|
-
});
|
|
1123
|
-
```
|
|
1124
|
-
|
|
1125
|
-
**McpServerConfig fields:**
|
|
1126
|
-
|
|
1127
|
-
| Field | Type | Default | Description |
|
|
1128
|
-
|-------|------|---------|-------------|
|
|
1129
|
-
| `transport` | `McpTransport` | `STDIO` | `STDIO`, `HTTP`, or `SSE` |
|
|
1130
|
-
| `command` | `string` | — | Command for stdio servers |
|
|
1131
|
-
| `args` | `string[]` | — | Command arguments |
|
|
1132
|
-
| `url` | `string` | — | URL for HTTP/SSE servers |
|
|
1133
|
-
| `headers` | `Record<string, string>` | — | HTTP headers |
|
|
1134
|
-
| `env` | `Record<string, string>` | — | Environment variables |
|
|
1135
|
-
| `enabledTools` | `string[]` | All | Tool allowlist |
|
|
1136
|
-
| `disabledTools` | `string[]` | — | Tool denylist |
|
|
1137
|
-
|
|
1138
|
-
### Platform-Specific Settings
|
|
1139
|
-
|
|
1140
|
-
#### Claude Code Settings
|
|
1141
|
-
|
|
1142
|
-
Configure Claude Code's `settings.json` with permissions, hooks, sandbox, and more:
|
|
1143
|
-
|
|
1144
|
-
```typescript
|
|
1145
|
-
new AgentConfig(project, {
|
|
1146
|
-
claudeSettings: {
|
|
1147
|
-
defaultMode: "default", // default, acceptEdits, plan, auto
|
|
1148
|
-
permissions: {
|
|
1149
|
-
allow: ["Bash(pnpm run *)", "Edit(/src/**/*.ts)"],
|
|
1150
|
-
deny: ["Bash(rm -rf *)"],
|
|
1151
|
-
ask: ["Bash"],
|
|
1152
|
-
additionalDirectories: ["/shared/libs"],
|
|
1153
|
-
},
|
|
1154
|
-
hooks: {
|
|
1155
|
-
PreToolUse: [
|
|
1156
|
-
{
|
|
1157
|
-
matcher: "Bash",
|
|
1158
|
-
hooks: [{ type: "command", command: "echo 'Running Bash'" }],
|
|
1159
|
-
},
|
|
1160
|
-
],
|
|
1161
|
-
},
|
|
1162
|
-
sandbox: { enabled: true },
|
|
1163
|
-
model: "claude-opus-4-6",
|
|
1164
|
-
effortLevel: "high",
|
|
1165
|
-
excludeSensitivePatterns: ["**/.env", "**/*.key"],
|
|
1166
|
-
},
|
|
1167
|
-
});
|
|
1168
|
-
```
|
|
1169
|
-
|
|
1170
|
-
#### Cursor Settings
|
|
1171
|
-
|
|
1172
|
-
Configure Cursor hooks and ignore patterns:
|
|
1173
|
-
|
|
1174
|
-
```typescript
|
|
1175
|
-
new AgentConfig(project, {
|
|
1176
|
-
cursorSettings: {
|
|
1177
|
-
hooks: {
|
|
1178
|
-
beforeShellExecution: [{ command: "echo 'pre-exec check'" }],
|
|
1179
|
-
afterFileEdit: [{ command: "pnpm run lint --fix" }],
|
|
1180
|
-
},
|
|
1181
|
-
ignorePatterns: ["**/.env", "**/secrets/**"],
|
|
1182
|
-
indexingIgnorePatterns: ["**/generated/**", "*.min.js"],
|
|
1183
|
-
},
|
|
1184
|
-
});
|
|
1185
|
-
```
|
|
1186
|
-
|
|
1187
|
-
### Template Variables
|
|
1188
|
-
|
|
1189
|
-
Rule content, skill instructions, and sub-agent prompts support `{{variable}}` template placeholders that are resolved from `ProjectMetadata` during synthesis:
|
|
1190
|
-
|
|
1191
|
-
| Variable | Fallback | Description |
|
|
1192
|
-
|----------|----------|-------------|
|
|
1193
|
-
| `{{repository.owner}}` | `<owner>` | GitHub repository owner |
|
|
1194
|
-
| `{{repository.name}}` | `<repo>` | Repository name |
|
|
1195
|
-
| `{{repository.defaultBranch}}` | `main` | Default branch |
|
|
1196
|
-
| `{{organization.name}}` | `<organization>` | Organization name |
|
|
1197
|
-
| `{{organization.githubOrg}}` | `<org>` | GitHub organization |
|
|
1198
|
-
| `{{githubProject.name}}` | `<project-name>` | GitHub project name |
|
|
1199
|
-
| `{{githubProject.number}}` | `<project-number>` | GitHub project number |
|
|
1200
|
-
| `{{githubProject.nodeId}}` | `<project-node-id>` | GitHub project node ID |
|
|
1201
|
-
| `{{docsPath}}` | `<docs-path>` | Documentation path |
|
|
1202
|
-
|
|
1203
|
-
If `ProjectMetadata` is not configured, fallback placeholders are used and a synthesis warning is emitted.
|
|
1204
|
-
|
|
1205
|
-
### Examples
|
|
1206
|
-
|
|
1207
|
-
**Minimal setup — all defaults:**
|
|
1208
|
-
|
|
1209
|
-
```typescript
|
|
1210
|
-
const project = new MonorepoProject({
|
|
1211
|
-
name: "my-project",
|
|
1212
|
-
agentConfig: true,
|
|
1213
|
-
});
|
|
1214
|
-
```
|
|
1215
|
-
|
|
1216
|
-
**Custom platform selection:**
|
|
1217
|
-
|
|
1218
|
-
```typescript
|
|
1219
|
-
import { AGENT_PLATFORM } from "@codedrifters/configulator";
|
|
1220
|
-
|
|
1221
|
-
const project = new MonorepoProject({
|
|
1222
|
-
name: "my-project",
|
|
1223
|
-
agentConfig: {
|
|
1224
|
-
platforms: [AGENT_PLATFORM.CLAUDE], // Claude only, no Cursor
|
|
1225
|
-
},
|
|
1226
|
-
});
|
|
1227
|
-
```
|
|
1228
|
-
|
|
1229
|
-
**Custom rules and skills:**
|
|
1230
|
-
|
|
1231
|
-
```typescript
|
|
1232
|
-
import { AGENT_RULE_SCOPE } from "@codedrifters/configulator";
|
|
1233
|
-
|
|
1234
|
-
const project = new MonorepoProject({
|
|
1235
|
-
name: "my-project",
|
|
1236
|
-
agentConfig: {
|
|
1237
|
-
rules: [
|
|
1238
|
-
{
|
|
1239
|
-
name: "database-conventions",
|
|
1240
|
-
description: "Database migration and query conventions",
|
|
1241
|
-
scope: AGENT_RULE_SCOPE.FILE_PATTERN,
|
|
1242
|
-
filePatterns: ["src/db/**/*.ts", "migrations/**/*.ts"],
|
|
1243
|
-
content: "# Database Conventions\n\n- Use parameterized queries\n- Never use raw SQL",
|
|
1244
|
-
},
|
|
1245
|
-
],
|
|
1246
|
-
skills: [
|
|
1247
|
-
{
|
|
1248
|
-
name: "migrate",
|
|
1249
|
-
description: "Run database migrations",
|
|
1250
|
-
instructions: "# Migrate\n\nRun `pnpm run db:migrate` and verify the schema.",
|
|
1251
|
-
allowedTools: ["Bash(pnpm run db:*)"],
|
|
1252
|
-
},
|
|
1253
|
-
],
|
|
1254
|
-
},
|
|
1255
|
-
});
|
|
1256
|
-
```
|
|
1257
|
-
|
|
1258
|
-
**Monorepo with per-package opt-in:**
|
|
1259
|
-
|
|
1260
|
-
`AgentConfig` is **not** auto-inherited by sub-projects. Agent rule files are
|
|
1261
|
-
rendered only on projects that explicitly opt in, so the monorepo root's
|
|
1262
|
-
`AgentConfig` does not duplicate `.cursor/`, `.claude/`, or `CLAUDE.md` into
|
|
1263
|
-
each sub-project's `outdir`. Sub-projects that opt in do still resolve
|
|
1264
|
-
`ProjectMetadata` from the root, so template tokens like
|
|
1265
|
-
`{{repository.owner}}` work without redeclaring metadata.
|
|
1266
|
-
|
|
1267
|
-
```typescript
|
|
1268
|
-
const root = new MonorepoProject({
|
|
1269
|
-
name: "my-monorepo",
|
|
1270
|
-
agentConfig: {
|
|
1271
|
-
// Root-level config — renders into the monorepo root only
|
|
1272
|
-
rules: [{ name: "monorepo-rule", description: "...", scope: AGENT_RULE_SCOPE.ALWAYS, content: "..." }],
|
|
1273
|
-
},
|
|
1274
|
-
});
|
|
1275
|
-
|
|
1276
|
-
// Sub-project with no agent config — nothing rendered into packages/api/
|
|
1277
|
-
const api = new TypeScriptProject({
|
|
1278
|
-
parent: root,
|
|
1279
|
-
name: "@my-org/api",
|
|
1280
|
-
outdir: "packages/api",
|
|
1281
|
-
});
|
|
1282
|
-
|
|
1283
|
-
// Sub-project that explicitly opts into its own agent config
|
|
1284
|
-
const frontend = new TypeScriptProject({
|
|
1285
|
-
parent: root,
|
|
1286
|
-
name: "@my-org/frontend",
|
|
1287
|
-
outdir: "packages/frontend",
|
|
1288
|
-
agentConfig: {
|
|
1289
|
-
// Only generate Claude config for this package
|
|
1290
|
-
platforms: [AGENT_PLATFORM.CLAUDE],
|
|
1291
|
-
excludeBundles: ["jest"], // This package uses Vitest, not Jest
|
|
1292
|
-
},
|
|
1293
|
-
});
|
|
1294
|
-
```
|
|
1295
|
-
|
|
1296
|
-
## Troubleshooting
|
|
1297
|
-
|
|
1298
|
-
**"Cannot find module" errors**
|
|
1299
|
-
|
|
1300
|
-
Run `npx projen` to regenerate configuration files.
|
|
1301
|
-
|
|
1302
|
-
**Turbo Repo cache errors**
|
|
1303
|
-
|
|
1304
|
-
- Ensure you've run the AWS login script
|
|
1305
|
-
- If it's your first run of the day, try running the command twice
|
|
1306
|
-
|
|
1307
|
-
**Build workflow failures**
|
|
1308
|
-
|
|
1309
|
-
Check that you haven't manually edited generated files. If you have, run `npx projen` to restore them.
|
|
1310
|
-
|
|
1311
|
-
**Dependency conflicts**
|
|
1312
|
-
|
|
1313
|
-
Don't mix `npm install` with Projen. Always add dependencies through configuration.
|
|
1314
|
-
|
|
1315
|
-
**Sub-project not appearing in workspace**
|
|
1316
|
-
|
|
1317
|
-
- Ensure the sub-project has `parent` set to the MonorepoProject
|
|
1318
|
-
- Ensure `outdir` is set correctly
|
|
1319
|
-
- Run `npx projen` to regenerate the workspace file
|
|
1320
|
-
|
|
1321
|
-
## Additional Resources
|
|
1322
|
-
|
|
1323
|
-
- **Projen Documentation:** https://projen.io
|
|
1324
|
-
- **Turbo Repo Docs:** https://turbo.build/repo/docs
|
|
1325
|
-
- **PNPM Workspaces:** https://pnpm.io/workspaces
|
|
1326
|
-
- **Code Drifters Configulator:** https://www.npmjs.com/package/@codedrifters/packages
|
|
1327
|
-
|
|
1328
|
-
---
|
|
1329
|
-
|
|
1330
|
-
**Remember:** The goal is consistency and automation. Let the tools manage the boilerplate so you can focus on building features.
|
|
7
|
+
**NPM:** [@codedrifters/configulator](https://www.npmjs.com/package/@codedrifters/configulator)
|