agentic-loop 1.0.0
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/.claude/commands/explain.md +114 -0
- package/.claude/commands/idea.md +398 -0
- package/.claude/commands/my-dna.md +122 -0
- package/.claude/commands/prd.md +286 -0
- package/.claude/commands/review.md +167 -0
- package/.claude/commands/sign.md +32 -0
- package/.claude/commands/styleguide.md +450 -0
- package/.claude/commands/tour.md +301 -0
- package/.claude/commands/vibe-check.md +116 -0
- package/.claude/commands/vibe-help.md +47 -0
- package/.claude/commands/vibe-list.md +203 -0
- package/.pre-commit-hooks.yaml +102 -0
- package/LICENSE +21 -0
- package/README.md +238 -0
- package/bin/agentic-loop.sh +24 -0
- package/bin/postinstall.sh +29 -0
- package/bin/ralph.sh +171 -0
- package/bin/vibe-check.js +19 -0
- package/dist/checks/check-any-types.d.ts +6 -0
- package/dist/checks/check-any-types.d.ts.map +1 -0
- package/dist/checks/check-any-types.js +73 -0
- package/dist/checks/check-any-types.js.map +1 -0
- package/dist/checks/check-commented-code.d.ts +6 -0
- package/dist/checks/check-commented-code.d.ts.map +1 -0
- package/dist/checks/check-commented-code.js +81 -0
- package/dist/checks/check-commented-code.js.map +1 -0
- package/dist/checks/check-console-error.d.ts +6 -0
- package/dist/checks/check-console-error.d.ts.map +1 -0
- package/dist/checks/check-console-error.js +41 -0
- package/dist/checks/check-console-error.js.map +1 -0
- package/dist/checks/check-debug-statements.d.ts +6 -0
- package/dist/checks/check-debug-statements.d.ts.map +1 -0
- package/dist/checks/check-debug-statements.js +120 -0
- package/dist/checks/check-debug-statements.js.map +1 -0
- package/dist/checks/check-deep-nesting.d.ts +6 -0
- package/dist/checks/check-deep-nesting.d.ts.map +1 -0
- package/dist/checks/check-deep-nesting.js +116 -0
- package/dist/checks/check-deep-nesting.js.map +1 -0
- package/dist/checks/check-docker-platform.d.ts +6 -0
- package/dist/checks/check-docker-platform.d.ts.map +1 -0
- package/dist/checks/check-docker-platform.js +42 -0
- package/dist/checks/check-docker-platform.js.map +1 -0
- package/dist/checks/check-dry-violations.d.ts +6 -0
- package/dist/checks/check-dry-violations.d.ts.map +1 -0
- package/dist/checks/check-dry-violations.js +124 -0
- package/dist/checks/check-dry-violations.js.map +1 -0
- package/dist/checks/check-empty-catch.d.ts +6 -0
- package/dist/checks/check-empty-catch.d.ts.map +1 -0
- package/dist/checks/check-empty-catch.js +111 -0
- package/dist/checks/check-empty-catch.js.map +1 -0
- package/dist/checks/check-function-length.d.ts +6 -0
- package/dist/checks/check-function-length.d.ts.map +1 -0
- package/dist/checks/check-function-length.js +152 -0
- package/dist/checks/check-function-length.js.map +1 -0
- package/dist/checks/check-hardcoded-ai-models.d.ts +10 -0
- package/dist/checks/check-hardcoded-ai-models.d.ts.map +1 -0
- package/dist/checks/check-hardcoded-ai-models.js +102 -0
- package/dist/checks/check-hardcoded-ai-models.js.map +1 -0
- package/dist/checks/check-hardcoded-urls.d.ts +6 -0
- package/dist/checks/check-hardcoded-urls.d.ts.map +1 -0
- package/dist/checks/check-hardcoded-urls.js +124 -0
- package/dist/checks/check-hardcoded-urls.js.map +1 -0
- package/dist/checks/check-magic-numbers.d.ts +6 -0
- package/dist/checks/check-magic-numbers.d.ts.map +1 -0
- package/dist/checks/check-magic-numbers.js +116 -0
- package/dist/checks/check-magic-numbers.js.map +1 -0
- package/dist/checks/check-secrets.d.ts +6 -0
- package/dist/checks/check-secrets.d.ts.map +1 -0
- package/dist/checks/check-secrets.js +138 -0
- package/dist/checks/check-secrets.js.map +1 -0
- package/dist/checks/check-snake-case-ts.d.ts +6 -0
- package/dist/checks/check-snake-case-ts.d.ts.map +1 -0
- package/dist/checks/check-snake-case-ts.js +78 -0
- package/dist/checks/check-snake-case-ts.js.map +1 -0
- package/dist/checks/check-todo-fixme.d.ts +6 -0
- package/dist/checks/check-todo-fixme.d.ts.map +1 -0
- package/dist/checks/check-todo-fixme.js +41 -0
- package/dist/checks/check-todo-fixme.js.map +1 -0
- package/dist/checks/check-unsafe-html.d.ts +6 -0
- package/dist/checks/check-unsafe-html.d.ts.map +1 -0
- package/dist/checks/check-unsafe-html.js +101 -0
- package/dist/checks/check-unsafe-html.js.map +1 -0
- package/dist/checks/index.d.ts +30 -0
- package/dist/checks/index.d.ts.map +1 -0
- package/dist/checks/index.js +57 -0
- package/dist/checks/index.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +208 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/file-reader.d.ts +24 -0
- package/dist/utils/file-reader.d.ts.map +1 -0
- package/dist/utils/file-reader.js +146 -0
- package/dist/utils/file-reader.js.map +1 -0
- package/dist/utils/patterns.d.ts +27 -0
- package/dist/utils/patterns.d.ts.map +1 -0
- package/dist/utils/patterns.js +84 -0
- package/dist/utils/patterns.js.map +1 -0
- package/dist/utils/reporters.d.ts +21 -0
- package/dist/utils/reporters.d.ts.map +1 -0
- package/dist/utils/reporters.js +115 -0
- package/dist/utils/reporters.js.map +1 -0
- package/dist/utils/types.d.ts +71 -0
- package/dist/utils/types.d.ts.map +1 -0
- package/dist/utils/types.js +5 -0
- package/dist/utils/types.js.map +1 -0
- package/package.json +83 -0
- package/ralph/api.sh +216 -0
- package/ralph/backup.sh +838 -0
- package/ralph/browser-verify/README.md +135 -0
- package/ralph/browser-verify/verify.ts +450 -0
- package/ralph/checks/check-fastapi-responses.py +155 -0
- package/ralph/hooks/hooks-config.json +72 -0
- package/ralph/hooks/inject-context.sh +44 -0
- package/ralph/hooks/install.sh +207 -0
- package/ralph/hooks/log-tools.sh +45 -0
- package/ralph/hooks/protect-prd.sh +27 -0
- package/ralph/hooks/save-learnings.sh +36 -0
- package/ralph/hooks/warn-debug.sh +54 -0
- package/ralph/hooks/warn-empty-catch.sh +63 -0
- package/ralph/hooks/warn-secrets.sh +89 -0
- package/ralph/hooks/warn-urls.sh +77 -0
- package/ralph/init.sh +515 -0
- package/ralph/loop.sh +730 -0
- package/ralph/playwright.sh +238 -0
- package/ralph/prd.sh +295 -0
- package/ralph/setup/feature-tour.sh +155 -0
- package/ralph/setup/quick-setup.sh +239 -0
- package/ralph/setup/tutorial.sh +159 -0
- package/ralph/setup/ui.sh +136 -0
- package/ralph/setup.sh +401 -0
- package/ralph/signs.sh +150 -0
- package/ralph/utils.sh +682 -0
- package/ralph/verify/browser.sh +324 -0
- package/ralph/verify/lint.sh +363 -0
- package/ralph/verify/review.sh +152 -0
- package/ralph/verify/tests.sh +81 -0
- package/ralph/verify.sh +268 -0
- package/templates/PROMPT.md +235 -0
- package/templates/config/fullstack.json +86 -0
- package/templates/config/go.json +81 -0
- package/templates/config/minimal.json +76 -0
- package/templates/config/node.json +81 -0
- package/templates/config/python.json +81 -0
- package/templates/config/rust.json +81 -0
- package/templates/examples/CLAUDE-django.md +174 -0
- package/templates/examples/CLAUDE-fastapi.md +270 -0
- package/templates/examples/CLAUDE-fastmcp.md +352 -0
- package/templates/examples/CLAUDE-fullstack.md +256 -0
- package/templates/examples/CLAUDE-node.md +246 -0
- package/templates/examples/CLAUDE-react.md +138 -0
- package/templates/optional/cursorrules.template +147 -0
- package/templates/optional/eslint.config.js +34 -0
- package/templates/optional/lint-staged.config.js +34 -0
- package/templates/optional/ruff.toml +125 -0
- package/templates/optional/vibe-check.yml +116 -0
- package/templates/optional/vscode-settings.json +127 -0
- package/templates/signs.json +46 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Project Instructions for AI Coding Agents
|
|
2
|
+
|
|
3
|
+
## Naming Conventions
|
|
4
|
+
- **Files**: `kebab-case.ts` — e.g., `user-service.ts`, `auth-middleware.ts`
|
|
5
|
+
- **Functions/Variables**: `camelCase` — e.g., `getUserById`, `isValid`
|
|
6
|
+
- **Classes/Interfaces/Types**: `PascalCase` — e.g., `UserService`, `CreateUserInput`
|
|
7
|
+
- **Constants**: `SCREAMING_SNAKE` — e.g., `MAX_RETRIES`, `DEFAULT_PORT`
|
|
8
|
+
- **Database tables**: `snake_case` — e.g., `user_sessions` (Prisma converts to camelCase)
|
|
9
|
+
- **API endpoints**: `kebab-case` — e.g., `/api/user-profile`, `/api/auth/sign-in`
|
|
10
|
+
|
|
11
|
+
## Tech Stack
|
|
12
|
+
- **Runtime**: Node.js 20+
|
|
13
|
+
- **Framework**: Express.js / Fastify
|
|
14
|
+
- **Language**: TypeScript
|
|
15
|
+
- **Database**: PostgreSQL with Prisma
|
|
16
|
+
- **Testing**: Jest, Supertest
|
|
17
|
+
|
|
18
|
+
## Code Quality Standards
|
|
19
|
+
|
|
20
|
+
### TypeScript
|
|
21
|
+
- Enable strict mode in tsconfig
|
|
22
|
+
- Never use `any` - define proper types
|
|
23
|
+
- Use `unknown` for truly dynamic data
|
|
24
|
+
- Export types from dedicated files
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
// types/user.ts
|
|
28
|
+
export interface User {
|
|
29
|
+
id: string;
|
|
30
|
+
email: string;
|
|
31
|
+
name: string;
|
|
32
|
+
createdAt: Date;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface CreateUserInput {
|
|
36
|
+
email: string;
|
|
37
|
+
name: string;
|
|
38
|
+
password: string;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### API Endpoints
|
|
43
|
+
- Use consistent response format
|
|
44
|
+
- Return appropriate HTTP status codes
|
|
45
|
+
- Validate all input with Zod or Joi
|
|
46
|
+
- Handle errors with middleware
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// Consistent response format
|
|
50
|
+
interface ApiResponse<T> {
|
|
51
|
+
success: boolean;
|
|
52
|
+
data?: T;
|
|
53
|
+
error?: {
|
|
54
|
+
code: string;
|
|
55
|
+
message: string;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Controller
|
|
60
|
+
export async function createUser(req: Request, res: Response) {
|
|
61
|
+
const input = createUserSchema.parse(req.body);
|
|
62
|
+
|
|
63
|
+
const user = await userService.create(input);
|
|
64
|
+
|
|
65
|
+
res.status(201).json({
|
|
66
|
+
success: true,
|
|
67
|
+
data: user,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Error Handling
|
|
73
|
+
- Use custom error classes
|
|
74
|
+
- Centralize error handling in middleware
|
|
75
|
+
- Log errors with context
|
|
76
|
+
- Never expose stack traces to clients
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// errors.ts
|
|
80
|
+
export class AppError extends Error {
|
|
81
|
+
constructor(
|
|
82
|
+
public statusCode: number,
|
|
83
|
+
public code: string,
|
|
84
|
+
message: string
|
|
85
|
+
) {
|
|
86
|
+
super(message);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export class NotFoundError extends AppError {
|
|
91
|
+
constructor(resource: string) {
|
|
92
|
+
super(404, 'NOT_FOUND', `${resource} not found`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// middleware/errorHandler.ts
|
|
97
|
+
export function errorHandler(
|
|
98
|
+
err: Error,
|
|
99
|
+
req: Request,
|
|
100
|
+
res: Response,
|
|
101
|
+
next: NextFunction
|
|
102
|
+
) {
|
|
103
|
+
logger.error('Request error', { error: err, path: req.path });
|
|
104
|
+
|
|
105
|
+
if (err instanceof AppError) {
|
|
106
|
+
return res.status(err.statusCode).json({
|
|
107
|
+
success: false,
|
|
108
|
+
error: { code: err.code, message: err.message },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Don't expose internal errors
|
|
113
|
+
res.status(500).json({
|
|
114
|
+
success: false,
|
|
115
|
+
error: { code: 'INTERNAL_ERROR', message: 'Something went wrong' },
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Database (Prisma)
|
|
121
|
+
- Use transactions for multi-step operations
|
|
122
|
+
- Select only needed fields
|
|
123
|
+
- Use pagination for list endpoints
|
|
124
|
+
- Add indexes in schema
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// Good - select only needed fields
|
|
128
|
+
const users = await prisma.user.findMany({
|
|
129
|
+
select: {
|
|
130
|
+
id: true,
|
|
131
|
+
email: true,
|
|
132
|
+
name: true,
|
|
133
|
+
},
|
|
134
|
+
take: 20,
|
|
135
|
+
skip: page * 20,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Transaction
|
|
139
|
+
await prisma.$transaction(async (tx) => {
|
|
140
|
+
const order = await tx.order.create({ data: orderData });
|
|
141
|
+
await tx.inventory.decrement({ where: { productId }, data: { quantity } });
|
|
142
|
+
return order;
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Async/Await
|
|
147
|
+
- Always use try/catch or error middleware
|
|
148
|
+
- Use Promise.all for parallel operations
|
|
149
|
+
- Handle promise rejections
|
|
150
|
+
- Avoid callback-style code
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
// Parallel operations
|
|
154
|
+
const [user, orders, notifications] = await Promise.all([
|
|
155
|
+
userService.getById(userId),
|
|
156
|
+
orderService.getByUser(userId),
|
|
157
|
+
notificationService.getUnread(userId),
|
|
158
|
+
]);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Security
|
|
162
|
+
- Validate all input
|
|
163
|
+
- Use parameterized queries (Prisma does this)
|
|
164
|
+
- Set security headers (helmet)
|
|
165
|
+
- Rate limit sensitive endpoints
|
|
166
|
+
- Never log sensitive data
|
|
167
|
+
|
|
168
|
+
### Logging
|
|
169
|
+
- Use structured logging (pino, winston)
|
|
170
|
+
- Include request ID for tracing
|
|
171
|
+
- Log appropriate levels
|
|
172
|
+
- Never log passwords or tokens
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
logger.info('User created', {
|
|
176
|
+
userId: user.id,
|
|
177
|
+
email: user.email,
|
|
178
|
+
// Never log: password, token, etc.
|
|
179
|
+
});
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Testing
|
|
183
|
+
- Unit test business logic
|
|
184
|
+
- Integration test API endpoints
|
|
185
|
+
- Mock external services
|
|
186
|
+
- Use test database
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
describe('POST /api/users', () => {
|
|
190
|
+
it('creates a user with valid input', async () => {
|
|
191
|
+
const response = await request(app)
|
|
192
|
+
.post('/api/users')
|
|
193
|
+
.send({ email: 'test@example.com', name: 'Test', password: 'secure123' });
|
|
194
|
+
|
|
195
|
+
expect(response.status).toBe(201);
|
|
196
|
+
expect(response.body.success).toBe(true);
|
|
197
|
+
expect(response.body.data.email).toBe('test@example.com');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('returns 400 for invalid email', async () => {
|
|
201
|
+
const response = await request(app)
|
|
202
|
+
.post('/api/users')
|
|
203
|
+
.send({ email: 'invalid', name: 'Test', password: 'secure123' });
|
|
204
|
+
|
|
205
|
+
expect(response.status).toBe(400);
|
|
206
|
+
expect(response.body.error.code).toBe('VALIDATION_ERROR');
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## File Structure
|
|
212
|
+
```
|
|
213
|
+
src/
|
|
214
|
+
├── controllers/ # Route handlers
|
|
215
|
+
├── services/ # Business logic
|
|
216
|
+
├── repositories/ # Database access
|
|
217
|
+
├── middleware/ # Express middleware
|
|
218
|
+
├── types/ # TypeScript types
|
|
219
|
+
├── utils/ # Helper functions
|
|
220
|
+
├── routes/ # Route definitions
|
|
221
|
+
└── index.ts # App entry point
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Environment Variables
|
|
225
|
+
```typescript
|
|
226
|
+
// config.ts
|
|
227
|
+
export const config = {
|
|
228
|
+
port: process.env.PORT || 3000,
|
|
229
|
+
databaseUrl: process.env.DATABASE_URL!,
|
|
230
|
+
jwtSecret: process.env.JWT_SECRET!,
|
|
231
|
+
nodeEnv: process.env.NODE_ENV || 'development',
|
|
232
|
+
};
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Pre-commit Hooks
|
|
236
|
+
This project uses agentic-loop hooks. Run `/vibe-check` before committing.
|
|
237
|
+
|
|
238
|
+
## Common Commands
|
|
239
|
+
```bash
|
|
240
|
+
npm run dev # Start dev server with hot reload
|
|
241
|
+
npm run build # Build TypeScript
|
|
242
|
+
npm start # Start production server
|
|
243
|
+
npm test # Run tests
|
|
244
|
+
npm run lint # Run linter
|
|
245
|
+
npm run db:migrate # Run Prisma migrations
|
|
246
|
+
```
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Project Instructions for AI Coding Agents
|
|
2
|
+
|
|
3
|
+
## Naming Conventions
|
|
4
|
+
- **Files**: `PascalCase.tsx` for components, `camelCase.ts` for utilities — e.g., `UserProfile.tsx`, `useAuth.ts`
|
|
5
|
+
- **Components**: `PascalCase` — e.g., `UserProfile`, `AuthProvider`
|
|
6
|
+
- **Hooks**: `useCamelCase` — e.g., `useAuth`, `useUserData`
|
|
7
|
+
- **Functions/Variables**: `camelCase` — e.g., `handleSubmit`, `isLoading`
|
|
8
|
+
- **Types/Interfaces**: `PascalCase` — e.g., `UserProps`, `AuthState`
|
|
9
|
+
- **Constants**: `SCREAMING_SNAKE` — e.g., `API_BASE_URL`, `MAX_RETRIES`
|
|
10
|
+
- **CSS classes**: `kebab-case` (TailwindCSS utility classes are standard)
|
|
11
|
+
|
|
12
|
+
## Tech Stack
|
|
13
|
+
- **Frontend**: React 18, TypeScript, Vite
|
|
14
|
+
- **Styling**: TailwindCSS
|
|
15
|
+
- **State**: React Query for server state, Zustand for client state
|
|
16
|
+
- **Testing**: Vitest, React Testing Library, Playwright
|
|
17
|
+
|
|
18
|
+
## Code Quality Standards
|
|
19
|
+
|
|
20
|
+
### TypeScript
|
|
21
|
+
- **Never use `any`** - Create proper interfaces for all data
|
|
22
|
+
- Use strict mode (`"strict": true` in tsconfig)
|
|
23
|
+
- Prefer `interface` for object shapes, `type` for unions/intersections
|
|
24
|
+
- Use `unknown` instead of `any` when type is truly unknown
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
// Bad
|
|
28
|
+
const data: any = await fetchUser();
|
|
29
|
+
|
|
30
|
+
// Good
|
|
31
|
+
interface User {
|
|
32
|
+
id: string;
|
|
33
|
+
email: string;
|
|
34
|
+
name: string;
|
|
35
|
+
}
|
|
36
|
+
const data: User = await fetchUser();
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### React Components
|
|
40
|
+
- Use functional components with hooks
|
|
41
|
+
- Keep components small and focused (< 100 lines)
|
|
42
|
+
- Extract logic into custom hooks
|
|
43
|
+
- Use proper TypeScript types for props
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// Good component structure
|
|
47
|
+
interface UserCardProps {
|
|
48
|
+
user: User;
|
|
49
|
+
onEdit: (user: User) => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function UserCard({ user, onEdit }: UserCardProps) {
|
|
53
|
+
return (/* ... */);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### State Management
|
|
58
|
+
- Use React Query for server state (caching, refetching)
|
|
59
|
+
- Use Zustand for UI state only
|
|
60
|
+
- Keep state as close to usage as possible
|
|
61
|
+
- Don't duplicate server state in client state
|
|
62
|
+
|
|
63
|
+
### Error Handling
|
|
64
|
+
- Always handle loading, error, and empty states
|
|
65
|
+
- Use Error Boundaries for unexpected errors
|
|
66
|
+
- Show user-friendly error messages
|
|
67
|
+
- Log errors with context for debugging
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Always handle all states
|
|
71
|
+
const { data, isLoading, error } = useQuery(['user'], fetchUser);
|
|
72
|
+
|
|
73
|
+
if (isLoading) return <Skeleton />;
|
|
74
|
+
if (error) return <ErrorMessage error={error} />;
|
|
75
|
+
if (!data) return <EmptyState />;
|
|
76
|
+
|
|
77
|
+
return <UserProfile user={data} />;
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Styling with TailwindCSS
|
|
81
|
+
- Use Tailwind utility classes
|
|
82
|
+
- Extract repeated patterns to components, not @apply
|
|
83
|
+
- Use design system tokens (colors, spacing)
|
|
84
|
+
- Keep className strings readable
|
|
85
|
+
|
|
86
|
+
### Testing
|
|
87
|
+
- Write tests for business logic and user interactions
|
|
88
|
+
- Use React Testing Library (test behavior, not implementation)
|
|
89
|
+
- Mock external dependencies
|
|
90
|
+
- Use Playwright for critical user flows
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// Test user behavior, not implementation
|
|
94
|
+
test('user can submit form', async () => {
|
|
95
|
+
render(<ContactForm />);
|
|
96
|
+
|
|
97
|
+
await userEvent.type(screen.getByLabelText(/email/i), 'test@example.com');
|
|
98
|
+
await userEvent.click(screen.getByRole('button', { name: /submit/i }));
|
|
99
|
+
|
|
100
|
+
expect(screen.getByText(/thanks/i)).toBeInTheDocument();
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## File Structure
|
|
105
|
+
```
|
|
106
|
+
src/
|
|
107
|
+
├── components/ # Reusable UI components
|
|
108
|
+
│ ├── ui/ # Design system primitives
|
|
109
|
+
│ └── features/ # Feature-specific components
|
|
110
|
+
├── hooks/ # Custom React hooks
|
|
111
|
+
├── pages/ # Page components (routes)
|
|
112
|
+
├── services/ # API calls and external services
|
|
113
|
+
├── stores/ # Zustand stores
|
|
114
|
+
├── types/ # TypeScript types/interfaces
|
|
115
|
+
└── utils/ # Helper functions
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Environment Variables
|
|
119
|
+
- Use `import.meta.env.VITE_*` for client-side env vars
|
|
120
|
+
- Never commit real secrets
|
|
121
|
+
- Provide defaults for local development
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000/api';
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Pre-commit Hooks
|
|
128
|
+
This project uses agentic-loop hooks. Run `/vibe-check` before committing.
|
|
129
|
+
|
|
130
|
+
## Common Commands
|
|
131
|
+
```bash
|
|
132
|
+
npm run dev # Start dev server
|
|
133
|
+
npm run build # Build for production
|
|
134
|
+
npm test # Run unit tests
|
|
135
|
+
npm run test:e2e # Run E2E tests
|
|
136
|
+
npm run lint # Run linter
|
|
137
|
+
npm run typecheck # Check types
|
|
138
|
+
```
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Cursor Rules for Vibe Coding
|
|
2
|
+
# Copy this file to your project root as `.cursorrules`
|
|
3
|
+
|
|
4
|
+
You are an expert developer helping with this project. Follow these rules:
|
|
5
|
+
|
|
6
|
+
## Code Quality
|
|
7
|
+
|
|
8
|
+
### Never Use These Patterns
|
|
9
|
+
- `any` type in TypeScript - create proper interfaces
|
|
10
|
+
- Empty catch blocks - handle errors properly
|
|
11
|
+
- `console.log` for error handling - use proper logging
|
|
12
|
+
- Hardcoded URLs - use environment variables
|
|
13
|
+
- Functions over 50 lines - break them up
|
|
14
|
+
- Deep nesting (4+ levels) - refactor with early returns
|
|
15
|
+
|
|
16
|
+
### Always Do This
|
|
17
|
+
- Handle loading, error, and empty states
|
|
18
|
+
- Use proper TypeScript types
|
|
19
|
+
- Write descriptive variable names
|
|
20
|
+
- Add error handling for async operations
|
|
21
|
+
- Use environment variables for configuration
|
|
22
|
+
|
|
23
|
+
## Response Format
|
|
24
|
+
|
|
25
|
+
When writing code:
|
|
26
|
+
1. Explain what you're doing briefly
|
|
27
|
+
2. Write clean, typed code
|
|
28
|
+
3. Include error handling
|
|
29
|
+
4. Mention any edge cases to consider
|
|
30
|
+
|
|
31
|
+
When I ask you to fix something:
|
|
32
|
+
1. Explain what was wrong
|
|
33
|
+
2. Show the fix
|
|
34
|
+
3. Explain why it's better
|
|
35
|
+
|
|
36
|
+
## TypeScript Rules
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// DON'T
|
|
40
|
+
const data: any = await fetch('/api');
|
|
41
|
+
function process(input: any): any { }
|
|
42
|
+
|
|
43
|
+
// DO
|
|
44
|
+
interface User { id: string; name: string; }
|
|
45
|
+
const data: User = await fetchUser();
|
|
46
|
+
function process(input: UserInput): ProcessedUser { }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Error Handling
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// DON'T
|
|
53
|
+
try { doThing(); } catch (e) { }
|
|
54
|
+
|
|
55
|
+
// DO
|
|
56
|
+
try {
|
|
57
|
+
await doThing();
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (error instanceof NetworkError) {
|
|
60
|
+
logger.warn('Network error, retrying', { error });
|
|
61
|
+
return retry(doThing);
|
|
62
|
+
}
|
|
63
|
+
logger.error('Failed to do thing', { error });
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## React Components
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// DON'T
|
|
72
|
+
function UserProfile({ userId }) {
|
|
73
|
+
const [user, setUser] = useState();
|
|
74
|
+
// No loading/error handling
|
|
75
|
+
return <div>{user.name}</div>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// DO
|
|
79
|
+
function UserProfile({ userId }: { userId: string }) {
|
|
80
|
+
const { data: user, isLoading, error } = useUser(userId);
|
|
81
|
+
|
|
82
|
+
if (isLoading) return <Skeleton />;
|
|
83
|
+
if (error) return <ErrorMessage error={error} />;
|
|
84
|
+
if (!user) return <NotFound />;
|
|
85
|
+
|
|
86
|
+
return <div>{user.name}</div>;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Testing
|
|
91
|
+
|
|
92
|
+
When I ask you to write tests:
|
|
93
|
+
1. Use the SCENARIO/EXPECTED/FAILURE pattern
|
|
94
|
+
2. Test behavior, not implementation
|
|
95
|
+
3. Include happy path and error cases
|
|
96
|
+
4. Keep tests independent
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
test('user can submit form', async () => {
|
|
100
|
+
/**
|
|
101
|
+
* SCENARIO: User fills out valid form and submits
|
|
102
|
+
* EXPECTED: Success message shown, form cleared
|
|
103
|
+
* FAILURE: Error shown or form stuck
|
|
104
|
+
*/
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Security
|
|
109
|
+
|
|
110
|
+
Never:
|
|
111
|
+
- Put secrets in code
|
|
112
|
+
- Use innerHTML with user content
|
|
113
|
+
- Build SQL queries with string concatenation
|
|
114
|
+
- Trust user input without validation
|
|
115
|
+
|
|
116
|
+
Always:
|
|
117
|
+
- Use parameterized queries
|
|
118
|
+
- Sanitize HTML if you must render it
|
|
119
|
+
- Validate input on both client and server
|
|
120
|
+
- Use HTTPS for external requests
|
|
121
|
+
|
|
122
|
+
## When Asked to Review Code
|
|
123
|
+
|
|
124
|
+
Check for:
|
|
125
|
+
1. Security vulnerabilities
|
|
126
|
+
2. Missing error handling
|
|
127
|
+
3. `any` types
|
|
128
|
+
4. Code duplication
|
|
129
|
+
5. Long functions
|
|
130
|
+
6. Missing tests for critical paths
|
|
131
|
+
|
|
132
|
+
## Project-Specific Notes
|
|
133
|
+
|
|
134
|
+
<!-- Add your project-specific patterns here -->
|
|
135
|
+
|
|
136
|
+
### Tech Stack
|
|
137
|
+
- Frontend: [Your stack]
|
|
138
|
+
- Backend: [Your stack]
|
|
139
|
+
- Database: [Your database]
|
|
140
|
+
|
|
141
|
+
### Patterns to Follow
|
|
142
|
+
- [Pattern 1]
|
|
143
|
+
- [Pattern 2]
|
|
144
|
+
|
|
145
|
+
### Things to Avoid
|
|
146
|
+
- [Anti-pattern 1]
|
|
147
|
+
- [Anti-pattern 2]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example ESLint configuration using agentic-loop plugin
|
|
3
|
+
*
|
|
4
|
+
* Copy this file to your project root and customize as needed.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import vibe from "agentic-loop/eslint-plugin";
|
|
8
|
+
|
|
9
|
+
export default [
|
|
10
|
+
// Use the recommended config (balanced defaults)
|
|
11
|
+
vibe.configs.recommended,
|
|
12
|
+
|
|
13
|
+
// Or use strict config for stricter rules
|
|
14
|
+
// vibe.configs.strict,
|
|
15
|
+
|
|
16
|
+
// Custom configuration
|
|
17
|
+
{
|
|
18
|
+
files: ["**/*.ts", "**/*.tsx"],
|
|
19
|
+
rules: {
|
|
20
|
+
// Override specific rules if needed
|
|
21
|
+
// "vibe/no-any-type": "error",
|
|
22
|
+
// "vibe/max-function-length": ["warn", { max: 40 }],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// Disable rules for test files
|
|
27
|
+
{
|
|
28
|
+
files: ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"],
|
|
29
|
+
rules: {
|
|
30
|
+
"vibe/no-magic-numbers": "off",
|
|
31
|
+
"vibe/max-function-length": "off",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ready-to-use lint-staged configuration for agentic-loop
|
|
3
|
+
*
|
|
4
|
+
* Copy this file to your project root, or reference the config:
|
|
5
|
+
*
|
|
6
|
+
* // package.json
|
|
7
|
+
* {
|
|
8
|
+
* "lint-staged": {
|
|
9
|
+
* "*.{js,ts,jsx,tsx}": "vibe-check --fail-on error"
|
|
10
|
+
* }
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
// JavaScript/TypeScript files - full security and quality checks
|
|
16
|
+
'*.{js,jsx,ts,tsx,mjs,cjs}': [
|
|
17
|
+
'vibe-check --only secrets,urls,debug,unsafe-html,any-types,snake-case,empty-catch --fail-on error',
|
|
18
|
+
],
|
|
19
|
+
|
|
20
|
+
// Python files
|
|
21
|
+
'*.py': [
|
|
22
|
+
'vibe-check --only secrets,urls,debug,empty-catch,magic-numbers --fail-on error',
|
|
23
|
+
],
|
|
24
|
+
|
|
25
|
+
// Config files - secrets check only
|
|
26
|
+
'*.{json,yaml,yml,toml}': [
|
|
27
|
+
'vibe-check --only secrets --fail-on error',
|
|
28
|
+
],
|
|
29
|
+
|
|
30
|
+
// Dockerfiles
|
|
31
|
+
'Dockerfile*': [
|
|
32
|
+
'vibe-check --only docker-platform --fail-on warning',
|
|
33
|
+
],
|
|
34
|
+
};
|