Cline is an open-source autonomous coding agent that lives directly in VS Code. Unlike autocomplete tools, Cline can create files, run terminal commands, and complete entire coding tasks independently. The key to getting great results is providing clear instructions and guidelines.
This guide provides ready-to-use rules that help Cline work effectively on your projects.
Cline is unique because it:
The transparency is key—you see and approve everything before it happens.
Cline has a built-in custom instructions feature:
Create .clinerules or .cline/instructions.md in your project root:
# Cline Instructions
[Your rules go here - Cline will reference this automatically]
Provide instructions directly when giving Cline a task:
"Following our TypeScript conventions (functional patterns, strict types),
create a user authentication service..."
## Task Execution Guidelines
- Break complex tasks into smaller, logical steps
- Ask for clarification if requirements are ambiguous
- Show a plan before implementing (outline the approach)
- Create tests alongside implementation code
- Run tests after implementation to verify functionality
- Format code before completing the task
- Provide a summary of changes made when done
## File Organization
- Create new files in appropriate directories based on project structure
- Follow existing naming conventions in the project
- Keep related files together (component + test + styles)
- Update imports in affected files after creating/moving files
## Code Style Standards
### General Principles
- Write self-documenting code with clear variable names
- Prefer readability over cleverness
- Keep functions small and focused (under 50 lines)
- Maximum 3 levels of nesting
- Use early returns to reduce nesting
- DRY (Don't Repeat Yourself) - extract common patterns
### Naming Conventions
- Variables and functions: camelCase
- Classes and components: PascalCase
- Constants: UPPER_SNAKE_CASE
- Boolean variables: prefix with is/has/should/can
- Private class members: prefix with underscore
- Event handlers: prefix with handle (handleClick, handleSubmit)
### Comments
- Use comments to explain "why", not "what"
- Complex algorithms need explanation
- TODO comments should include context and date
- Remove commented-out code (use git history instead)
## TypeScript/JavaScript Standards
### Type Safety
```typescript
// ✅ Do this
interface User {
id: string;
email: string;
name: string;
role: 'admin' | 'user' | 'guest';
}
const fetchUser = async (id: string): Promise<User> => {
const response = await api.get<User>(`/users/${id}`);
return response.data;
};
// ❌ Avoid this
const fetchUser = async (id: any): Promise<any> => {
const response = await api.get('/users/' + id);
return response.data;
};
### Modern JavaScript
- Use `const` by default, `let` only when reassignment needed
- Never use `var`
- Prefer arrow functions for callbacks
- Use template literals instead of string concatenation
- Destructuring for object and array access
- Async/await over promise chains
- Optional chaining (`?.`) for safe property access
- Nullish coalescing (`??`) for default values
### Module System
- Named exports preferred over default exports
- Group imports: external → internal → relative → types
- Sort imports alphabetically within groups
- Use barrel exports (index.ts) for cleaner imports
## React Development Standards
### Component Structure
```typescript
// Standard component template
interface ButtonProps {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary';
disabled?: boolean;
}
export const Button = ({
label,
onClick,
variant = 'primary',
disabled = false
}: ButtonProps) => {
// 1. Hooks
const [isLoading, setIsLoading] = useState(false);
// 2. Derived state
const buttonClass = useMemo(() => {
return `btn btn-${variant} ${disabled ? 'disabled' : ''}`;
}, [variant, disabled]);
// 3. Event handlers
const handleClick = useCallback(async () => {
if (disabled) return;
setIsLoading(true);
try {
await onClick();
} finally {
setIsLoading(false);
}
}, [disabled, onClick]);
// 4. Render
return (
<button
className={buttonClass}
onClick={handleClick}
disabled={disabled || isLoading}
>
{isLoading ? 'Loading...' : label}
</button>
);
};
## Python Development Standards
### Code Style (PEP 8)
```python
# ✅ Good Python code
from typing import List, Optional
from dataclasses import dataclass
from datetime import datetime
@dataclass
class User:
"""Represents a user in the system."""
id: str
email: str
name: str
created_at: datetime
is_active: bool = True
def get_active_users(
users: List[User],
min_created_date: Optional[datetime] = None
) -> List[User]:
"""
Filter users by active status and optional creation date.
Args:
users: List of User objects to filter
min_created_date: Optional minimum creation date filter
Returns:
Filtered list of active users
Raises:
ValueError: If users list is empty
"""
if not users:
raise ValueError("Users list cannot be empty")
active_users = [u for u in users if u.is_active]
if min_created_date:
active_users = [
u for u in active_users
if u.created_at >= min_created_date
]
return active_users
with statement) for resourcesexcept: - always specify exception type## Testing Standards
### Test Coverage Requirements
- Minimum 80% code coverage overall
- 100% coverage for critical business logic
- Test happy path, edge cases, and error conditions
- Integration tests for feature workflows
- E2E tests for critical user journeys
### Test Structure (Arrange-Act-Assert)
```typescript
describe('UserService', () => {
describe('createUser', () => {
it('should successfully create a new user with valid data', async () => {
// Arrange
const userData = {
email: 'test@example.com',
name: 'Test User',
password: 'SecurePass123!'
};
const mockDb = createMockDatabase();
const service = new UserService(mockDb);
// Act
const result = await service.createUser(userData);
// Assert
expect(result.success).toBe(true);
expect(result.data).toMatchObject({
email: userData.email,
name: userData.name
});
expect(result.data.id).toBeDefined();
expect(mockDb.insert).toHaveBeenCalledTimes(1);
});
it('should reject user creation with invalid email', async () => {
// Arrange
const invalidUserData = {
email: 'not-an-email',
name: 'Test User',
password: 'SecurePass123!'
};
const service = new UserService(createMockDatabase());
// Act
const result = await service.createUser(invalidUserData);
// Assert
expect(result.success).toBe(false);
expect(result.error).toContain('Invalid email format');
});
it('should handle database errors gracefully', async () => {
// Arrange
const userData = { email: 'test@example.com', name: 'Test', password: 'Pass123!' };
const mockDb = createMockDatabase();
mockDb.insert.mockRejectedValue(new Error('Database connection failed'));
const service = new UserService(mockDb);
// Act
const result = await service.createUser(userData);
// Assert
expect(result.success).toBe(false);
expect(result.error).toContain('Failed to create user');
});
});
});
## API Development Standards
### RESTful API Conventions
Resource: users
GET /api/v1/users - List users (paginated)
GET /api/v1/users/:id - Get specific user
POST /api/v1/users - Create new user
PUT /api/v1/users/:id - Update entire user
PATCH /api/v1/users/:id - Partial update user
DELETE /api/v1/users/:id - Delete user
Nested resources:
GET /api/v1/users/:id/posts - Get user's posts
POST /api/v1/users/:id/posts - Create post for user
// Success response
{
success: true,
data: {
id: "123",
email: "user@example.com",
name: "John Doe"
},
meta?: {
pagination?: {
page: 1,
pageSize: 20,
totalPages: 5,
totalItems: 100
}
}
}
// Error response
{
success: false,
error: {
message: "User not found",
code: "USER_NOT_FOUND",
details?: {
userId: "123"
}
}
}
## Database Standards
### Schema Design
```sql
-- Standard table structure
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP NULL -- Soft delete
);
-- Add indexes for frequently queried columns
CREATE INDEX idx_users_email ON users(email) WHERE deleted_at IS NULL;
CREATE INDEX idx_users_created_at ON users(created_at) WHERE deleted_at IS NULL;
// ✅ Use ORM with proper typing
const users = await prisma.user.findMany({
where: {
deletedAt: null,
isActive: true
},
select: {
id: true,
email: true,
name: true
},
orderBy: {
createdAt: 'desc'
},
take: 50
});
// ❌ Avoid raw SQL (SQL injection risk)
const users = await prisma.$queryRaw`
SELECT * FROM users WHERE email = ${email}
`;
// ✅ If raw SQL needed, use parameterized queries
const users = await prisma.$queryRaw`
SELECT * FROM users WHERE email = ${email}
`;
## Security Standards
### Environment & Secrets
```bash
# .env file structure
DATABASE_URL=postgresql://user:pass@localhost:5432/db
API_KEY=your-api-key-here
JWT_SECRET=your-jwt-secret-here
NODE_ENV=development
Security Rules:
import { z } from 'zod';
// Define validation schema
const UserCreateSchema = z.object({
email: z.string().email('Invalid email format'),
password: z.string()
.min(8, 'Password must be at least 8 characters')
.regex(/[A-Z]/, 'Password must contain uppercase letter')
.regex(/[0-9]/, 'Password must contain number'),
name: z.string()
.min(2, 'Name must be at least 2 characters')
.max(100, 'Name must be less than 100 characters')
});
// Validate input
const validateUserInput = (input: unknown) => {
try {
return UserCreateSchema.parse(input);
} catch (error) {
if (error instanceof z.ZodError) {
throw new ValidationError(error.errors);
}
throw error;
}
};
## Error Handling Standards
### Async Error Handling
```typescript
// ✅ Proper async error handling
async function fetchUserData(id: string): Promise<Result<User>> {
try {
const response = await api.get(`/users/${id}`);
return {
success: true,
data: response.data
};
} catch (error) {
// Log with context
console.error('Failed to fetch user:', {
userId: id,
error: error instanceof Error ? error.message : 'Unknown error'
});
// Return user-friendly error
if (axios.isAxiosError(error)) {
if (error.response?.status === 404) {
return {
success: false,
error: 'User not found'
};
}
if (error.response?.status === 403) {
return {
success: false,
error: 'Access denied'
};
}
}
return {
success: false,
error: 'Failed to fetch user data. Please try again later.'
};
}
}
export class AppError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number = 500,
public isOperational: boolean = true
) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
export class ValidationError extends AppError {
constructor(message: string, public fields?: Record<string, string>) {
super(message, 'VALIDATION_ERROR', 400);
}
}
export class NotFoundError extends AppError {
constructor(resource: string, id: string) {
super(`${resource} with id ${id} not found`, 'NOT_FOUND', 404);
}
}
export class UnauthorizedError extends AppError {
constructor(message: string = 'Unauthorized') {
super(message, 'UNAUTHORIZED', 401);
}
}
## Git Conventions
### Commit Message Format (Conventional Commits)
<type>(<scope>): <subject>
<body>
<footer>
feat(auth): implement password reset flow
Add email-based password reset with secure token generation.
Tokens expire after 1 hour for security.
Closes #234
---
fix(api): handle null response from payment service
Payment service occasionally returns null instead of error object.
Added null check and appropriate error handling.
Fixes #456
---
refactor(components): extract common button styles
Created shared Button component to reduce code duplication
across Login, Register, and Profile components.
### Documentation Rules
```markdown
## Documentation Standards
### Code Documentation
```typescript
/**
* Processes a payment transaction with the payment provider.
*
* This function handles the complete payment flow including validation,
* provider communication, and transaction recording. If the payment fails,
* it will be automatically retried up to 3 times with exponential backoff.
*
* @param paymentData - Payment information including amount, currency, and method
* @param userId - ID of the user making the payment
* @returns Promise resolving to transaction result with transaction ID
*
* @throws {ValidationError} If payment data is invalid
* @throws {PaymentError} If payment provider rejects the transaction
* @throws {NetworkError} If unable to reach payment provider after retries
*
* @example
* ```typescript
* const result = await processPayment({
* amount: 99.99,
* currency: 'USD',
* method: 'credit_card',
* token: 'tok_...'
* }, 'user_123');
*
* if (result.success) {
* console.log('Transaction ID:', result.transactionId);
* }
* ```
*/
async function processPayment(
paymentData: PaymentData,
userId: string
): Promise<TransactionResult> {
// Implementation
}
# Project Name
Brief description of what this project does.
## Features
- Feature 1
- Feature 2
- Feature 3
## Tech Stack
- Frontend: React, TypeScript, Tailwind CSS
- Backend: Node.js, Express, PostgreSQL
- Testing: Jest, React Testing Library
## Getting Started
### Prerequisites
- Node.js 18+
- PostgreSQL 14+
- npm or yarn
### Installation
\```bash
# Clone the repository
git clone https://github.com/username/project.git
# Install dependencies
cd project
npm install
# Set up environment variables
cp .env.example .env
# Edit .env with your configuration
# Run database migrations
npm run db:migrate
# Start development server
npm run dev
\```
### Running Tests
\```bash
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # With coverage report
\```
## Project Structure
\```
src/
├── components/ # React components
├── pages/ # Page components
├── lib/ # Utility functions
├── services/ # API services
├── hooks/ # Custom React hooks
└── types/ # TypeScript types
\```
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md)
## License
MIT
Follow the coding standards in .clinerules file.
When creating new features:
1. Show implementation plan first
2. Create tests alongside code
3. Run tests to verify
4. Format code before completion
5. Provide summary of changes
Create .clinerules in project root:
# Cline Project Rules
## Tech Stack
- React 18 with TypeScript
- Next.js 14 (App Router)
- Tailwind CSS
- PostgreSQL with Prisma
- Jest + React Testing Library
## Standards
[Copy relevant rules from this guide]
## Current Focus
- Building user authentication system
- Follow security best practices strictly
When giving Cline a task:
"Create a user profile component following our React standards:
- TypeScript with proper interfaces
- Functional component with hooks
- Include loading and error states
- Write tests (happy path + error cases)
- Use Tailwind for styling
The component should display user info and allow editing."
Cline shows every change before executing:
Instead of: "Build complete authentication system"
Do this:
Step 1: "Create database schema for users table with email, password_hash"
Step 2: "Implement user registration API endpoint with validation"
Step 3: "Add password hashing with bcrypt"
Step 4: "Create login endpoint with JWT generation"
Step 5: "Add authentication middleware"
After implementation:
"Now run the tests you created to verify everything works"
Cline will execute tests and fix issues if they fail.
"Refactor the UserService class to:
- Extract validation logic into separate validator
- Improve error handling with custom error classes
- Add JSDoc documentation
- Ensure all existing tests still pass"
"Create a new 'products' feature with:
- Product model in src/models/Product.ts
- Product service in src/services/ProductService.ts
- Product API routes in src/pages/api/products/
- React components in src/components/products/
- Tests for all of the above
Follow existing project patterns."
## Next.js Standards
- Use App Router (not Pages Router)
- Server Components by default
- Mark client components with 'use client' directive
- Use Server Actions for form submissions
- Implement proper loading.tsx and error.tsx
- Metadata API for SEO
app/
├── (marketing)/
│ ├── page.tsx # Homepage (Server Component)
│ └── about/
│ └── page.tsx
├── (app)/
│ ├── layout.tsx
│ ├── dashboard/
│ │ ├── page.tsx
│ │ ├── loading.tsx
│ │ └── error.tsx
│ └── settings/
│ └── page.tsx
└── api/
└── v1/
└── users/
└── route.ts # API Route Handler
## Express.js Standards
- Use TypeScript for type safety
- Async route handlers with express-async-errors
- Centralized error handling middleware
- Request validation middleware (express-validator or Zod)
- Helmet for security headers
- Rate limiting on all routes
- CORS configuration
src/
├── routes/
│ ├── index.ts
│ └── users.ts
├── controllers/
│ └── userController.ts
├── services/
│ └── userService.ts
├── models/
│ └── User.ts
├── middleware/
│ ├── auth.ts
│ ├── errorHandler.ts
│ └── validation.ts
└── app.ts
Problem: Code doesn't match your conventions
Solution:
Problem: Cline makes extensive changes you can't review properly
Solution:
Problem: Cline creates code but tests don't pass
Solution:
"The tests are failing. Please:
1. Review the test output
2. Fix the implementation
3. Run tests again to verify
4. Explain what was wrong"
Problem: Cline creates files in incorrect directories
Solution: Be explicit about file paths
"Create UserService.ts in src/services/ directory (not src/lib/)"
Here's a complete task example with all context:
Task: Create user profile feature
Context:
- Project uses Next.js 14 App Router with TypeScript
- Database: PostgreSQL with Prisma ORM
- Styling: Tailwind CSS
- Testing: Jest + React Testing Library
Requirements:
1. Create Prisma schema for user profiles (add to existing schema)
- Fields: bio (text), avatar_url (string), location (string)
2. Create API endpoint: PATCH /api/v1/users/[id]/profile
- Validate input with Zod
- Update user profile in database
- Return updated profile data
3. Create ProfileEdit component (app/dashboard/profile/edit)
- Form with bio, avatar, location fields
- Client component with form state
- Handle submit with Server Action
- Show loading and error states
- Success message after save
4. Write tests:
- API endpoint tests (happy path + validation)
- Component tests (render, submit, error handling)
Follow our coding standards:
- TypeScript strict mode
- Functional components with hooks
- Proper error handling
- 80% test coverage
Please show me the plan first, then implement step by step.
Last Updated: January 2026
Cline's autonomous capabilities are powerful when guided with clear instructions. Start with small tasks to build trust, then gradually delegate more complex work as you refine your rules and communication style!