Skip to content

Commit 0fc4d96

Browse files
authored
fix: Simplify AGENTS.md by moving coding standards to CONTRIBUTING.md (#504)
1 parent 7fb4f94 commit 0fc4d96

File tree

2 files changed

+77
-158
lines changed

2 files changed

+77
-158
lines changed

AGENTS.md renamed to CLAUDE.md

Lines changed: 5 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -186,149 +186,11 @@ Once the MCP server is configured, test the MCP tools by:
186186

187187
## Coding guidelines
188188

189-
### Indentation
190-
191-
We use **4 spaces** for indentation (configured in `.editorconfig`).
192-
193-
### Naming conventions
194-
195-
- **Constants**: Use uppercase `SNAKE_CASE` for global, immutable constants (e.g., `ACTOR_MAX_MEMORY_MBYTES`, `SERVER_NAME`)
196-
- **Functions & Variables**: Use `camelCase` format (e.g., `fetchActorDetails`, `actorClient`)
197-
- **Classes, Types, Interfaces**: Use `PascalCase` format (e.g., `ActorsMcpServer`, `ActorDetailsResult`)
198-
- **Files & Folders**: Use lowercase `snake_case` format (e.g., `actor_details.ts`, `key_value_store.ts`)
199-
- **Booleans**: Prefix with `is`, `has`, or `should` (e.g., `isValid`, `hasFinished`, `shouldRetry`)
200-
- **Units**: Suffix with the unit of measure (e.g., `intervalMillis`, `maxMemoryBytes`)
201-
- **Date/Time**: Suffix with `At` (e.g., `createdAt`, `updatedAt`)
202-
- **Zod Validators**: Suffix with `Validator` (e.g., `InputValidator`)
203-
204-
### Types and interfaces
205-
206-
- Prefer `type` for flexibility.
207-
- Use `interface` only when it's required for class implementations (`implements`).
208-
209-
### Types organization
210-
211-
- **Centralize shared/public types**: Put cross-module domain types and public API types in `src/types.ts`.
212-
- **Co-locate local types**: Keep module- or feature-specific types next to their usage (in the same file or a local `types.ts`).
213-
- **Use a folder-level `types.ts`** when multiple files in a folder share types, instead of inflating the root `src/types.ts`.
214-
215-
### Comments
216-
217-
- Use JSDoc style comments (`/** */`) for functions, interfaces, enums, and classes
218-
- Use `//` for generic inline comments
219-
- Avoid `/* */` multiline comments (single asterisk)
220-
- Use proper English (spelling, grammar, punctuation, capitalization)
221-
222-
### Code structure
223-
224-
- **Avoid `else`**: Return early to reduce indentation and keep logic flat
225-
- **Keep functions small**: Small, focused functions are easier to understand and test
226-
- **Minimal parameters**: Functions should only accept what they actually use
227-
- Use comma-separated parameters for up to three parameters
228-
- Use a single object parameter for more than three parameters
229-
- **Declare variables close to use**: Variables should be declared near their first use
230-
- **Extract reusable logic**: Extract complex or reusable logic into named helper functions
231-
- **Avoid intermediate variables for single-use expressions**: Don't create constants or variables if they're only used once. Inline them directly. For example:
232-
- ❌ Don't: `const docSourceEnum = z.enum([...]); const schema = z.object({ docSource: docSourceEnum })`
233-
- ✅ Do: `const schema = z.object({ docSource: z.enum([...]) })`
234-
- Exception: Only create intermediate variables if they improve readability for complex expressions or serve a documentation purpose
235-
236-
### Async functions
237-
238-
- Use `async` and `await` over `Promise` and `then` calls
239-
- Use `await` when you care about the Promise result or exceptions
240-
- Use `void` when you don't need to wait for the Promise (fire-and-forget)
241-
- Use `return await` when returning Promises to preserve accurate stack traces
242-
243-
### Imports and import ordering
244-
245-
- Imports are automatically ordered and grouped by ESLint:
246-
- Groups: builtin → external → parent/sibling → index → object
247-
- Alphabetized within groups
248-
- Newlines between groups
249-
- Use `import type` for type-only imports
250-
- Do not duplicate imports – always reuse existing imports if present
251-
- Do not use dynamic imports unless explicitly told to do so
252-
253-
### Error handling
254-
255-
- **User errors**: Use appropriate error codes (4xx for client errors), log as `softFail`
256-
- **Internal errors**: Use appropriate error codes (5xx for server errors), log with `log.exception` or `log.error`
257-
- Always handle and propagate errors clearly
258-
- Use custom error classes from `src/errors.ts` when appropriate
259-
- **Don't log then throw**: Do NOT call `log.error()` immediately before throwing. Errors are already logged by the caller or error handler. This creates duplicate logs and violates separation of concerns.
260-
- ❌ Don't:
261-
```typescript
262-
if (!indexConfig) {
263-
const error = `Unknown documentation source: ${docSource}`;
264-
log.error(`[Algolia] ${error}`);
265-
throw new Error(error);
266-
}
267-
```
268-
-Do:
269-
```typescript
270-
if (!indexConfig) {
271-
throw new Error(`Unknown documentation source: ${docSource}`);
272-
}
273-
```
274-
275-
### Code quality
276-
277-
- All files must follow ESLint rules (run `npm run lint` before committing)
278-
- Prefer readability over micro-optimizations
279-
- Avoid mutating function parameters (use immutability when possible)
280-
- If mutation is necessary, clearly document and explain it with a comment
281-
- Clean up temporary files, scripts, or helper files created during development
282-
283-
### Common patterns
284-
285-
- **Tool implementation**: Tools are defined in `src/tools/` using Zod schemas for validation
286-
- **Actor interaction**: Use `src/utils/apify-client.ts` for Apify API calls, never call Apify API directly
287-
- **Error responses**: Return user-friendly error messages with suggestions
288-
- **Input validation**: Always validate tool inputs with Zod before processing
289-
- **Caching**: Use TTL-based caching for Actor schemas and details (see `src/utils/ttl-lru.ts`)
290-
- **Constants and Tool Names**: Always use constants and never magic or hardcoded values. When referring to tools, ALWAYS use the `HelperTools` enum.
291-
- **Exception**: Integration tests (`tests/integration/`) must use hardcoded strings for tool names. This ensures tests fail if a tool is renamed, helping to prevent accidental breaking changes.
292-
293-
### Input validation best practices
294-
295-
- **No double validation**: When using Zod schemas with AJV validation (`ajvValidate` in tool definitions), do NOT add additional manual validation checks in the tool implementation. The Zod schema and AJV both validate inputs before the tool is executed. Any checks redundant to the schema definition should be removed.
296-
-Don't: Define enum validation in Zod, then manually check the enum again in the tool function
297-
-Do: Let Zod and AJV handle all validation; use the parsed data directly in the tool implementation
298-
299-
### Anti-patterns
300-
301-
- **Don't** call Apify API directly – always use the Apify client utilities
302-
- **Don't** mutate function parameters without clear documentation
303-
- **Don't** skip input validation – all tool inputs must be validated with Zod
304-
- **Don't** use `Promise.then()` - prefer `async/await`
305-
- **Don't** create tools without proper error handling and user-friendly messages
306-
307-
308-
### Design System Compliance (MANDATORY)
309-
310-
**READ FIRST**: [DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md](DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md) - Complete design system rules
311-
312-
**Quick Rules** (Zero tolerance):
313-
-ALWAYS use `theme.*` tokens (colors, spacing)
314-
-NEVER hardcode: `#hex`, `rgb()`, `Npx` values, font sizes
315-
-Import from `@apify/ui-library` only
316-
-Check `mcp__storybook__*` and `mcp__figma__*` availability before UI work
317-
-Call `mcp__storybook__get-ui-building-instructions` first
318-
-Read 1-3 similar components for patterns (max 3 files)
319-
-Verify zero hardcoded values before submitting
320-
321-
**Figma Integration**: Call `mcp__figma__get_design_context` when working from designs.
322-
323-
### What NOT to do (beyond code)
324-
325-
- Don't add features not in the requirements
326-
- Don't refactor working code unless asked
327-
- Don't add error handling for impossible scenarios
328-
- Don't create abstractions for one-time operations
329-
- Don't optimize prematurely
330-
- Don't add configuration for things that won't change
331-
- Don't suggest "improvements" outside current task scope
189+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for all coding standards, common patterns, anti-patterns, and design system rules.
190+
191+
## Branching strategy
192+
193+
Follow [CONTRIBUTING.md](./CONTRIBUTING.md) for commit message format, PR best practices, and coding standards.
332194

333195
## External dependencies
334196

CONTRIBUTING.md

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ All pull requests are subject to automated and manual review against these guide
55

66
---
77

8-
## 1. Commit Messages and PR Titles
8+
## Commit Messages and PR Titles
99

1010
All commits and PR titles must follow the **[Conventional Commits](https://www.conventionalcommits.org/)** format.
1111
Both the **type** (`feat`, `fix`, `chore`, etc.) and the **scope** (the component in parentheses) are required.
@@ -17,16 +17,16 @@ It applies to both commit messages and PR titles, since PRs are merged using squ
1717
### Examples of Good Messages
1818

1919
```text
20-
feat: add new tool for fetching actor details
21-
feat!: migrate to new MCP SDK version [internal]
22-
fix: handle connection errors gracefully
23-
refactor: improve type definitions [ignore]
24-
chore: update dependencies
20+
feat: Add new tool for fetching actor details
21+
feat!: Migrate to new MCP SDK version [internal]
22+
fix: Handle connection errors gracefully
23+
refactor: Improve type definitions [ignore]
24+
chore: Update dependencies
2525
```
2626

2727
---
2828

29-
## 2. Pull Request Descriptions
29+
## Pull Request Descriptions
3030

3131
Your PR description should extend your commit message:
3232
- Explain **what**, **why**, and **how**.
@@ -36,7 +36,7 @@ Your PR description should extend your commit message:
3636

3737
---
3838

39-
## 3. Pull Request Comments
39+
## Pull Request Comments
4040

4141
Use comments to guide reviewers:
4242
- Flag code that was **just moved**, so they don't re-review it.
@@ -45,14 +45,14 @@ Use comments to guide reviewers:
4545

4646
---
4747

48-
## 4. Pull Request Size
48+
## Pull Request Size
4949

5050
- Aim for ≤ **300 lines changed**.
5151
- Large PRs should be split into smaller, focused changes.
5252

5353
---
5454

55-
## 5. Coding Standards & Pitfalls
55+
## Coding Standards & Pitfalls
5656

5757
### Key reminders
5858
* **Keep logic flat**: avoid deep nesting and unnecessary `else`; return early instead.
@@ -139,22 +139,38 @@ Use comments to guide reviewers:
139139
* Prefer `type` for flexibility.
140140
* Use `interface` only when it's required for class implementations (`implements`).
141141

142+
* **Types organization:**
143+
* Centralize shared/public types in `src/types.ts`.
144+
* Co-locate module-specific types next to their usage (same file or a local `types.ts`).
145+
* Use a folder-level `types.ts` when multiple files in a folder share types, instead of inflating the root `src/types.ts`.
146+
142147
* **Code Structure:**
143148
* Keep functions short, focused, and cohesive.
144149
* Declare variables close to their first use.
145150
* Extract reusable or complex logic into named helper functions.
151+
* **Avoid intermediate variables for single-use expressions**don't create a variable if it's only used once; inline it directly.
152+
*Don't: `const docSourceEnum = z.enum([...]); const schema = z.object({ docSource: docSourceEnum })`
153+
*Do: `const schema = z.object({ docSource: z.enum([...]) })`
154+
* Exception: Only create intermediate variables if they improve readability for complex expressions.
146155

147156
* **Immutability:**
148157
* Avoid mutating function parameters.
149158
* If mutation is absolutely necessary (e.g., for performance), clearly document and explain it with a comment.
150159

160+
* **Imports:**
161+
* Imports are ordered and grouped automatically by ESLint: builtinexternalparent/siblingindexobject, alphabetized within groups, with newlines between groups.
162+
* Use `import type` for type-only imports.
163+
* Do not duplicate importsreuse existing ones.
164+
* Do not use dynamic imports unless explicitly required.
165+
151166
* **Readability vs. Performance:**
152167
* Prioritize readability over micro-optimizations.
153168
* For performance-critical code, optimize only when justified and document the reasoning.
154169

155170
* **Assertions & Validations:**
156171
* Use **Zod** for schema-based validation of complex shapes or intricate checks.
157172
* Use **custom validators and assertions** for lightweight, in-code checks - e.g. validating primitive values, simple shapes, or decision logic inside functions.
173+
* **No double validation:** When using Zod schemas with AJV (`ajvValidate` in tool definitions), do NOT add redundant manual validationlet the schema handle it. Use the parsed data directly.
158174

159175
* **Error Handling:**
160176
* **User Errors:**
@@ -163,6 +179,9 @@ Use comments to guide reviewers:
163179
* **Internal Errors:**
164180
* Use appropriate error codes (5xx for server errors).
165181
* Log with `log.exception`, `log.error`, or appropriate error logging.
182+
* **Don't log then throw:** Do NOT call `log.error()` immediately before throwing — the error will be logged by the caller. This creates duplicate logs and violates separation of concerns.
183+
*Don't: `log.error('Something failed'); throw new Error('Something failed');`
184+
*Do: `throw new Error('Something failed');`
166185

167186
* **Logging:**
168187
* Log meaningful information for debugging, especially errors in critical system parts.
@@ -178,15 +197,53 @@ Use comments to guide reviewers:
178197
* Sanitize data before sending or logging.
179198
* Use appropriate data structures to limit exposed fields.
180199

200+
* **Common patterns:**
201+
* **Tool implementation**: Tools are defined in `src/tools/` using Zod schemas for validation.
202+
* **Actor interaction**: Use `src/utils/apify-client.ts` for Apify API callsnever call the Apify API directly.
203+
* **Error responses**: Return user-friendly error messages with suggestions.
204+
* **Input validation**: Always validate tool inputs with Zod before processing.
205+
* **Caching**: Use TTL-based caching for Actor schemas and details (see `src/utils/ttl-lru.ts`).
206+
* **Constants and tool names**: Always use constants and never hardcoded values. When referring to tools, ALWAYS use the `HelperTools` enum.
207+
* Exception: Integration tests (`tests/integration/`) must use hardcoded strings for tool names. This ensures tests fail if a tool is renamed, preventing accidental breaking changes.
208+
209+
* **Anti-patterns:**
210+
* Don't call Apify API directly — always use the Apify client utilities.
211+
* Don't mutate function parameters without clear documentation.
212+
* Don't skip input validation — all tool inputs must be validated with Zod.
213+
* Don't use `Promise.then()` — prefer `async/await`.
214+
* Don't create tools without proper error handling and user-friendly messages.
215+
* Don't add features not in the requirements.
216+
* Don't refactor working code unless asked.
217+
* Don't add error handling for impossible scenarios.
218+
* Don't create abstractions for one-time operations.
219+
* Don't optimize prematurely.
220+
221+
---
222+
223+
## Design System Compliance (MANDATORY)
224+
225+
**READ FIRST**: [DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md](DESIGN_SYSTEM_AGENT_INSTRUCTIONS.md) — Complete design system rules.
226+
227+
**Quick Rules** (Zero tolerance):
228+
-ALWAYS use `theme.*` tokens (colors, spacing)
229+
-NEVER hardcode: `#hex`, `rgb()`, `Npx` values, font sizes
230+
-Import from `@apify/ui-library` only
231+
-Check `mcp__storybook__*` and `mcp__figma__*` availability before UI work
232+
-Call `mcp__storybook__get-ui-building-instructions` first
233+
-Read 1-3 similar components for patterns (max 3 files)
234+
-Verify zero hardcoded values before submitting
235+
236+
**Figma Integration**: Call `mcp__figma__get_design_context` when working from designs.
237+
181238
---
182239

183-
## 6. Development Setup
240+
## Development Setup
184241

185242
For local development setup, scripts, and manual testing, see [DEVELOPMENT.md](./DEVELOPMENT.md).
186243

187244
---
188245

189-
## 7. Code Review Guidelines
246+
## Code Review Guidelines
190247

191248
- Make **two passes** on substantial PRs:
192249
- First: understand changes at a high level.
@@ -196,7 +253,7 @@ For local development setup, scripts, and manual testing, see [DEVELOPMENT.md](.
196253

197254
---
198255

199-
## 8. Testing
256+
## Testing
200257

201258
- Write tests for new features and bug fixes.
202259
- Ensure all tests pass before submitting a PR.
@@ -205,15 +262,15 @@ For local development setup, scripts, and manual testing, see [DEVELOPMENT.md](.
205262

206263
---
207264

208-
## 9. Documentation
265+
## Documentation
209266

210267
- Update README.md if adding new features or changing behavior.
211268
- Add JSDoc comments for public APIs.
212269
- Keep code comments clear and concise.
213270

214271
---
215272

216-
## 10. Questions?
273+
## Questions?
217274

218275
If you have questions or need help, please:
219276
- Open an issue for discussion

0 commit comments

Comments
 (0)