Zed employs a straightforward architecture for AI coding assistance:
User Opens Project
↓
Zed Scans Project Root
↓
Loads First Matching Rule File (Priority Order)
↓
Reads Model Config from .zed/settings.json
↓
User Opens Agent Panel (cmd-shift-?)
↓
AI Receives:
- Model configuration
- Entire rules file content (as system prompt)
- Current file context
- User's request
↓
AI Generates Response Following Rules
↓
User Reviews and Applies Changes
Key Architectural Principles:
| Principle | Implementation | Impact |
|---|---|---|
| Zero Parsing | Rules passed as-is to LLM | Maximum flexibility, no schema constraints |
| Single File Loading | Only first matching file used | Simple but requires file priority awareness |
| Full Content Injection | Entire file added to system prompt | Token efficiency critical |
| Session Persistence | Rules loaded once per session | Changes require restart/reload |
| Format Agnostic | Any Markdown structure works | Easy migration from other tools |
1.2 What Zed Does NOT Do
Understanding limitations prevents confusion:
❌ No TOML for AI Rules — Despite Zed using TOML for extensions (extension.toml), AI rules are pure Markdown
❌ No Conditional Loading — Cannot load different rules per file type (unlike Cursor's globs)
❌ No Frontmatter Parsing — YAML headers ignored (entire file treated as text)
❌ No Multi-File Merging — Only loads single rule file (unlike Windsurf's .windsurf/rules/ directory)
❌ No Rule Validation — Typos and errors not caught by Zed
1.3 File System Architecture
Project Structure:
my-project/
├── .rules # Zed-specific (PRIORITY 1)
├── .cursorrules # Cursor compatibility (PRIORITY 2)
├── .windsurfrules # Windsurf compatibility (PRIORITY 3)
├── AGENTS.md # Universal standard (PRIORITY 6)
├── .zed/
│ └── settings.json # Editor config + model selection
├── src/
└── tests/
Global Configuration:
~/.config/zed/
├── settings.json # User-level settings
└── (no global rules directory) # Rules must be per-project
2. The Dual Configuration System
2.1 JSON for Machine Configuration
File: .zed/settings.json (project) or ~/.config/zed/settings.json (global)
Purpose: Configure editor behavior, LSP, formatters, and AI models
Structure:
{
// Visual appearance
"theme": "One Dark",
"buffer_font_size": 14,
"ui_font_size": 16,
// Language Server Protocol
"lsp": {
"typescript-language-server": {
"initialization_options": {
"preferences": {
"includeInlayParameterNameHints": "all",
"includeInlayFunctionParameterTypeHints": true
}
}
},
"rust-analyzer": {
"initialization_options": {
"check": {
"command": "clippy"
}
}
}
},
// Code formatting
"formatter": {
"language_server": {
"name": "prettier"
}
},
// AI Model Configuration
"agent": {
"default_model": {
"provider": "anthropic",
"model": "claude-3-5-sonnet-20241022"
},
"inline_assistant_model": {
"provider": "openai",
"model": "gpt-4o-mini"
}
},
// Language-specific settings
"languages": {
"TypeScript": {
"tab_size": 2,
"format_on_save": "on",
"code_actions_on_format": {
"source.organizeImports": true
}
},
"Rust": {
"tab_size": 4,
"format_on_save": "on"
}
}
}
Key Configuration Areas:
AI Agent Configuration
{
"agent": {
// Primary model for Agent Panel conversations
"default_model": {
"provider": "anthropic", // anthropic, openai, ollama, google
"model": "claude-3-5-sonnet-20241022"
},
// Fast model for inline suggestions
"inline_assistant_model": {
"provider": "openai",
"model": "gpt-4o-mini"
}
}
}
Available Providers:
-
anthropic— Claude models (Sonnet, Opus, Haiku) -
openai— GPT-4o, GPT-4o-mini, o1, o3 -
google— Gemini models -
ollama— Local models (e.g.,ollama/qwen2.5-coder)
Language Server Configuration
{
"lsp": {
"typescript-language-server": {
"initialization_options": {
"preferences": {
// Inline hints
"includeInlayParameterNameHints": "all",
"includeInlayFunctionParameterTypeHints": true,
"includeInlayVariableTypeHints": true,
// Import handling
"includeCompletionsForModuleExports": true,
"includeCompletionsWithInsertText": true,
// Strict mode
"strictNullChecks": true,
"strictFunctionTypes": true
}
}
}
}
}
2.2 Markdown for AI Instructions
File: .rules (or compatible alternatives)
Purpose: Natural language guidance for AI code generation
Structure:
# Project Rules
## Tech Stack
[Stack definition]
## Coding Standards
[Style guidelines with examples]
## Patterns
[Architectural patterns]
## Testing
[Test requirements]
Why Markdown?
| Aspect | Advantage |
|---|---|
| Native LLM Training | Models trained on Markdown documentation |
| Rich Formatting | Headers, lists, tables, code blocks |
| Human Readable | Easy to write and review |
| Git Friendly | Clean diffs, semantic line breaks |
| Cross-Tool | Works with Cursor, Windsurf, Claude Code, etc. |
| No Schema | Zero learning curve |
3. Rule File Formats and Priority
3.1 File Discovery Order
Zed scans project root in this exact order:
| Priority | Filename | Tool Origin | Action |
|---|---|---|---|
| 1 | .rules |
Zed native | ✅ Use this (recommended) |
| 2 | .cursorrules |
Cursor IDE | ✅ Use if sharing with Cursor users |
| 3 | .windsurfrules |
Windsurf | ✅ Use if sharing with Windsurf users |
| 4 | .clinerules |
Cline | ✅ Use if sharing with Cline users |
| 5 | .github/copilot-instructions.md |
GitHub Copilot | ✅ Use if sharing with Copilot users |
| 6 |
AGENT.md or AGENTS.md
|
Universal standard | ✅ Best for multi-tool teams |
| 7 | CLAUDE.md |
Claude Code | ✅ Use if sharing with Claude Code users |
| 8 | GEMINI.md |
Gemini CLI | ✅ Use if sharing with Gemini users |
Critical Rule: Only the first matching file is loaded. If you have both .rules and .cursorrules, Zed uses .rules and ignores .cursorrules.
3.2 Choosing Your Strategy
Strategy 1: Zed-Only Project
# Create Zed-specific file
touch .rules
Strategy 2: Multi-Tool Team
# Use universal standard
touch AGENTS.md
# Zed finds it (priority 6)
# Other tools also recognize it
Strategy 3: Tool-Specific with Symlinks
# Master file
touch AGENTS.md
# Create symlink for Zed
ln -s AGENTS.md .rules
# Now updating AGENTS.md updates all tools
Strategy 4: Separate Files (Not Recommended)
# Requires maintaining multiple files
touch .rules # For Zed
touch .cursorrules # For Cursor
touch AGENTS.md # For others
# High maintenance burden
3.3 Verification Commands
Check which file Zed loads:
# List files in priority order
ls -la .rules .cursorrules .windsurfrules .clinerules AGENTS.md CLAUDE.md 2>/dev/null
# First file found is what Zed uses
Test rule loading:
- Open Zed
- Open Agent Panel (
cmd-shift-?or sparkles icon) - Ask: "What are the top 3 coding standards for this project?"
- Verify AI mentions rules from your file
4. Creating Your First .rules File
4.1 Quick Start Template
Minimal Working Example (50 lines):
# Project Rules
## Tech Stack
- TypeScript, React, Node.js
- PostgreSQL database
- Testing with Vitest
## Core Standards
1. TypeScript strict mode
2. Functional React components only
3. Async/await (no .then() chains)
4. All functions have explicit return types
5. Test coverage >80%
## Error Handling
Use Result<T> type:
typescript
type Result =
| { success: true; data: T }
| { success: false; error: string };
## Testing
- Unit tests required for business logic
- Run `npm test` before committing
- Use AAA pattern (Arrange, Act, Assert)
Save and test:
# Save to project root
vim .rules
# Restart Zed or reload window
# cmd-shift-p → "zed: reload window"
# Test in Agent Panel
# Ask: "Write a function to fetch user data"
# Verify: AI uses Result<T> type
4.2 Incremental Expansion Strategy
Week 1: Minimum Viable Rules (100 lines)
# Project Rules
## Tech Stack
[Your stack]
## Top 10 Standards
1. [Standard 1]
2. [Standard 2]
...
10. [Standard 10]
## Error Handling Pattern
[One example]
## Testing Requirements
[Basic requirements]
Week 2-3: Add Examples (200 lines)
For each standard, add:
- ❌ Bad example
- ✅ Good example
- Brief explanation
Week 4+: Add Edge Cases (300-500 lines)
Add sections for:
- Known issues and workarounds
- Common pitfalls
- Architecture patterns
- Deployment procedures
4.3 File Location Best Practices
Recommended Structure:
my-project/
├── .rules # Primary rules file
├── .zed/
│ ├── settings.json # Project settings
│ └── tasks.json # Custom tasks
├── docs/
│ ├── architecture.md # Detailed architecture
│ └── api-reference.md # API documentation
└── src/
Referencing External Docs in Rules:
# Project Rules
## Architecture
For complete architecture diagrams and decisions, see `docs/architecture.md`.
Key principles:
- Feature-sliced design
- Dependency injection
- Repository pattern
## API Conventions
Full API documentation: `docs/api-reference.md`
Quick reference:
- All endpoints return `{ success, data, error }`
- Rate limit: 100 req/min
5. Complete Rules File Structure
5.1 Optimal Section Hierarchy
Research-Backed Structure (500-line target):
# [Project Name] Rules for Zed AI
**Version:** 1.0.0
**Last Updated:** 2025-11-29
**Tech Stack:** [Brief stack summary]
---
## 1. PROJECT OVERVIEW (50 lines)
### 1.1 What This Project Does
[2-3 sentences]
### 1.2 Primary Goals
- Goal 1
- Goal 2
- Goal 3
### 1.3 Current Focus
[Sprint/milestone focus]
---
## 2. TECHNOLOGY STACK (100 lines)
### 2.1 Frontend
- Framework: [Name + version]
- Language: [Name + version]
- Styling: [Solution]
- State: [Management approach]
### 2.2 Backend
- Runtime: [Name + version]
- Framework: [Name + version]
- Database: [Name + version]
- ORM: [Name + version]
### 2.3 DevOps
- Package Manager: [Name]
- Monorepo: [Tool if applicable]
- Testing: [Framework(s)]
- CI/CD: [Platform]
- Hosting: [Platform]
---
## 3. PROJECT STRUCTURE (50 lines)
src/
├── app/ # [Description]
├── components/ # [Description]
├── lib/ # [Description]
└── tests/ # [Description]
**Key Directories:**
- `src/app/`: [Purpose and organization]
- `src/components/`: [Purpose and organization]
- `src/lib/`: [Purpose and organization]
---
## 4. CODING STANDARDS (150 lines)
### 4.1 TypeScript Rules
#### Type Annotations
typescript
// ✅ ALWAYS: Explicit return types
export function calculate(x: number): number {
return x * 2;
}
// ❌ NEVER: Implicit return types
export function calculate(x: number) {
return x * 2;
}
#### Avoid `any`
typescript
// ✅ Use unknown + type guards
function process(data: unknown) {
if (typeof data === 'object') {
// Safe
}
}
// ❌ Never use any
function process(data: any) {
// Unsafe
}
### 4.2 React Patterns
#### Component Structure
tsx
// ✅ Functional with types
interface Props {
user: User;
onEdit: (id: string) => void;
}
export function UserCard({ user, onEdit }: Props) {
return
}
// ❌ No inline types
export function UserCard({ user, onEdit }: any) {
return
}
### 4.3 Error Handling
[Pattern with examples]
### 4.4 Import Organization
[Order with examples]
---
## 5. TESTING REQUIREMENTS (50 lines)
### 5.1 Coverage Targets
- Unit: 80% minimum
- Integration: 70% minimum
- E2E: Critical flows only
### 5.2 Commands
bash
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report
### 5.3 Structure
typescript
describe('Feature', () => {
it('should handle happy path', () => {
// AAA pattern
});
});
---
## 6. COMMON COMMANDS (30 lines)
bash
npm run dev # Start development
npm run build # Production build
npm run lint # Run linter
npm run type-check # TypeScript check
---
## 7. KNOWN ISSUES (40 lines)
### Issue 1: [Title]
**Symptom:** [Description]
**Solution:** [Fix]
### Issue 2: [Title]
**Symptom:** [Description]
**Solution:** [Fix]
---
## 8. IMPORTANT NOTES (30 lines)
- API rate limit: 100 req/min
- JWT expiration: 15 minutes
- Environment variables: NEXT_PUBLIC_* for client
- Git workflow: Feature branches + PR
---
## WORKING WITH ZED AI
When using Agent Panel:
- Be specific about file locations
- Request diffs for review
- Verify changes before accepting
---
*Optimized for Zed AI Assistant*
5.2 Section Content Guidelines
Project Overview Section
## PROJECT OVERVIEW
### What This Project Does
E-commerce platform for small businesses. Handles product catalog,
shopping cart, checkout, and order management. Supports multi-tenant
architecture with row-level security.
### Primary Goals
- **Performance:** <100ms API response times
- **Scale:** Support 10,000 concurrent users
- **Availability:** 99.9% uptime SLA
### Current Sprint Focus
- Implementing shopping cart persistence
- Payment gateway integration (Stripe)
- Order confirmation emails
Why This Matters:
- Orients AI immediately to project domain
- Prevents generic solutions
- Focuses on current priorities
Technology Stack Section
## TECHNOLOGY STACK
### Frontend
- **Framework:** Next.js 15.1.0 (App Router, NOT Pages Router)
- **Language:** TypeScript 5.4.5 (strict mode enabled)
- **Styling:** Tailwind CSS 4.0.0
- **Components:** shadcn/ui + Radix UI primitives
- **State Management:**
- Server State: TanStack Query v5.56.2
- Client State: Zustand 4.5.2
- Forms: React Hook Form 7.53.0 + Zod 3.23.8
### Backend
- **Runtime:** Node.js 20.11.0 LTS
- **Framework:** Express.js 4.19.2 + tRPC 11.0.0
- **Database:** PostgreSQL 16.3
- **ORM:** Drizzle ORM 0.35.3
- **Auth:** NextAuth.js v5 (Auth.js)
### DevOps
- **Package Manager:** pnpm 9.0.6 (**NOT** npm or yarn)
- **Monorepo:** Turborepo 2.0.14
- **Testing:** Vitest 2.0.5, Playwright 1.45.3
- **CI/CD:** GitHub Actions
- **Hosting:** Vercel (production), Railway (staging)
Why Versions Matter:
- API differences between versions (Next.js 14 vs 15)
- Breaking changes (React 18 vs 19)
- Feature availability (TypeScript 5.4 features)
Coding Standards Section
Structure Every Rule As:
### Rule Title
#### Context (When This Applies)
[When to use this pattern]
#### ❌ WRONG (Anti-Pattern)
typescript
// Bad code with explanation
[Why it's wrong]
#### ✅ CORRECT (Recommended)
typescript
// Good code with explanation
[Why it's better]
#### Benefits
- [Benefit 1]
- [Benefit 2]
Example:
### Error Handling in Async Operations
#### Context
All async operations that can fail (API calls, database queries,
file operations) must use explicit error handling.
#### ❌ WRONG: Silent Failure
typescript
async function fetchUser(id: string) {
try {
return await api.get(/users/${id});
} catch {
return null; // Error swallowed silently!
}
}
**Problems:**
- Errors lost, impossible to debug
- Calling code can't distinguish "not found" from "server error"
- No logging for monitoring
#### ✅ CORRECT: Result Type Pattern
typescript
type Result =
| { success: true; data: T }
| { success: false; error: string };
async function fetchUser(id: string): Promise> {
try {
const response = await api.get(/users/${id});
return { success: true, data: response.data };
} catch (error) {
logger.error('fetchUser failed', { id, error });
return { success: false, error: 'Failed to fetch user' };
}
}
**Benefits:**
- Explicit success/failure handling
- Type-safe error checking
- Logged for debugging
- User-friendly error messages
6. Model Configuration in Settings
6.1 Accessing Settings Files
Project Settings:
# Location
.zed/settings.json
# Open in Zed
cmd-shift-p → "zed: open settings"
# Then select "Project Settings"
Global Settings:
# Location
~/.config/zed/settings.json
# Open in Zed
cmd-shift-p → "zed: open settings"
# Then select "User Settings"
6.2 AI Model Configuration
Complete Agent Configuration:
{
"agent": {
// Primary chat model (Agent Panel)
"default_model": {
"provider": "anthropic",
"model": "claude-3-5-sonnet-20241022"
},
// Fast inline assistant
"inline_assistant_model": {
"provider": "openai",
"model": "gpt-4o-mini"
}
}
}
Model Selection Strategy:
| Use Case | Recommended Model | Provider | Cost | Speed |
|---|---|---|---|---|
| Complex Refactoring | claude-3-5-sonnet-20241022 | Anthropic | $$$ | Medium |
| General Coding | gpt-4o | OpenAI | $$ | Fast |
| Quick Fixes | gpt-4o-mini | OpenAI | $ | Very Fast |
| Local Development | qwen2.5-coder:7b | Ollama | Free | Fast |
| Reasoning Tasks | o1 | OpenAI | $$$$ | Slow |
6.3 Provider-Specific Configuration
Anthropic (Claude)
{
"agent": {
"default_model": {
"provider": "anthropic",
"model": "claude-3-5-sonnet-20241022"
// API key from environment: ANTHROPIC_API_KEY
}
}
}
Available Models:
-
claude-3-5-sonnet-20241022— Best balance (recommended) -
claude-3-opus-20240229— Most capable (expensive) -
claude-3-haiku-20240307— Fastest (cheaper)
API Key Setup:
# Add to shell profile (~/.zshrc or ~/.bashrc)
export ANTHROPIC_API_KEY="sk-ant-xxx"
# Restart Zed to load environment variables
OpenAI (GPT)
{
"agent": {
"default_model": {
"provider": "openai",
"model": "gpt-4o"
// API key from environment: OPENAI_API_KEY
}
}
}
Available Models:
-
gpt-4o— Best for coding -
gpt-4o-mini— Fast and cheap -
o1— Deep reasoning (slower, expensive) -
o3-mini— Reasoning optimized
API Key Setup:
export OPENAI_API_KEY="sk-xxx"
Ollama (Local Models)
{
"agent": {
"default_model": {
"provider": "ollama",
"model": "qwen2.5-coder:7b"
// No API key needed (local)
}
}
}
Setup Process:
# Install Ollama
brew install ollama
# Start Ollama service
ollama serve
# Pull model
ollama pull qwen2.5-coder:7b
# Zed connects to localhost:11434 automatically
Recommended Local Models:
-
qwen2.5-coder:7b— Best coding model -
deepseek-coder:6.7b— Alternative -
codellama:13b— Meta's model
Google (Gemini)
{
"agent": {
"default_model": {
"provider": "google",
"model": "gemini-2.0-flash-exp"
// API key from environment: GOOGLE_API_KEY
}
}
}
Available Models:
-
gemini-2.0-flash-exp— Fast, experimental -
gemini-1.5-pro— Production stable
6.4 Multi-Model Strategy
Recommended Setup:
{
"agent": {
// Powerful model for complex tasks
"default_model": {
"provider": "anthropic",
"model": "claude-3-5-sonnet-20241022"
},
// Fast model for inline suggestions
"inline_assistant_model": {
"provider": "openai",
"model": "gpt-4o-mini"
}
}
}
When to Switch Models:
| Task | Model | Why |
|---|---|---|
| Multi-file refactoring | Claude 3.5 Sonnet | Best at understanding codebase context |
| Quick inline edits | GPT-4o-mini | Fast, cheap, good enough for simple tasks |
| Bug investigation | Claude 3.5 Sonnet | Superior reasoning |
| Boilerplate generation | GPT-4o-mini | Fast, cheap |
| Architecture planning | Claude 3 Opus | Most capable |
| Local/offline work | Qwen 2.5 Coder | No internet required |
Switching Models:
Currently requires editing .zed/settings.json and reloading. Zed may add UI switcher in future.
7. Global vs Project Rules
7.1 Project Rules (Recommended)
Location: ./rules in project root
Scope: Single project only
Use For:
- Project-specific tech stack
- Team coding standards
- Architecture patterns
- API conventions
- Deployment procedures
Example:
# ProjectX Rules
## Tech Stack
Next.js 15, TypeScript, PostgreSQL
## Team Standards
- Result<T> error handling
- Functional React components
- TanStack Query for data fetching
## Architecture
Feature-sliced design in src/features/
Version Control:
# Commit project rules with code
git add .rules
git commit -m "docs: add AI coding rules for TypeScript standards"
7.2 Global Rules (Not Supported Natively)
Zed Limitation: Unlike Cursor (~/Documents/Cursor/Rules) or Windsurf (~/.codeium/windsurf/memories), Zed has no global rules directory.
Workaround 1: Personal Template
# Create template
mkdir -p ~/Code/templates
vim ~/Code/templates/rules-template.md
# Copy to new projects
cp ~/Code/templates/rules-template.md ~/new-project/.rules
Workaround 2: Shell Script
# ~/bin/init-zed-rules
#!/bin/bash
cat > .rules << 'EOF'
# Personal Coding Standards
## My Preferences
- Functional programming patterns
- Explicit over implicit
- Comments for complex logic
## TypeScript
- Strict mode always
- Explicit return types
- No any types
## Testing
- Write tests after implementation (not TDD)
- Integration tests > unit tests
EOF
echo "✅ .rules file created"
# Make executable
chmod +x ~/bin/init-zed-rules
# Use in new projects
cd ~/new-project
init-zed-rules
Workaround 3: Git Template Directory
# Setup
mkdir -p ~/.git-templates/hooks
vim ~/.git-templates/.rules
# [Add your personal rules]
# Configure git
git config --global init.templateDir ~/.git-templates
# New repos automatically include .rules
git init new-project
cd new-project
ls -la .rules # File exists!
7.3 Hybrid Strategy
Combine Personal + Project Rules:
# .rules
## Project-Specific Rules
### Tech Stack
Next.js 15, TypeScript, PostgreSQL, tRPC
### Team Standards
[Project-specific standards]
---
## Personal Preferences (Developer-Specific)
### Code Style
- I prefer explicit > clever
- I write comments explaining "why", not "what"
- I use TODO comments for future improvements
### Workflow
- I commit frequently with conventional commits
- I write tests after implementation
- I prefer smaller PRs (< 300 lines)
### Response Format
- Show me diffs, not full file content
- Explain breaking changes explicitly
- Highlight security considerations
Team Agreement:
- Top section: Team standards (everyone follows)
- Bottom section: Personal preferences (optional, can vary)
8. Cross-Tool Compatibility
8.1 Multi-Tool Team Scenarios
Scenario 1: Team Uses Zed + Cursor + Windsurf
Solution: Universal AGENTS.md with Symlinks
# Create master file
vim AGENTS.md
# [Add all project rules]
# Symlinks for each tool
ln -s AGENTS.md .rules # Zed
ln -s AGENTS.md .cursorrules # Cursor
ln -s AGENTS.md .windsurfrules # Windsurf
ln -s AGENTS.md .clinerules # Cline
# Commit everything
git add AGENTS.md .rules .cursorrules .windsurfrules .clinerules
git commit -m "docs: setup universal AI rules with symlinks"
Result:
- Single source of truth (AGENTS.md)
- All tools read same rules
- One file to maintain
- Clean git diffs
Verification:
# Check symlinks
ls -la .rules .cursorrules .windsurfrules
# Should show:
# .rules -> AGENTS.md
# .cursorrules -> AGENTS.md
# .windsurfrules -> AGENTS.md
8.2 Portability Patterns
Pattern 1: AGENTS.md as Primary
# Use universal standard
touch AGENTS.md
# Zed finds it (priority 6)
# Cursor finds it (fallback)
# Windsurf finds it (fallback)
# Claude Code finds it (priority 2)
# Aider can load it
Advantages:
- ✅ One file, all tools
- ✅ Emerging standard (20k+ projects)
- ✅ No symlink complexity
- ✅ Works without any tool-specific files
Disadvantages:
- ⚠️ Lower priority in Zed (6th)
- ⚠️ If someone creates
.rules, AGENTS.md ignored
Pattern 2: Explicit Symlinks
# Master file
vim RULES_MASTER.md
# Symlinks for all tools
ln -s RULES_MASTER.md .rules
ln -s RULES_MASTER.md .cursorrules
ln -s RULES_MASTER.md AGENTS.md
Advantages:
- ✅ Explicit file presence
- ✅ Zed priority 1 (.rules)
- ✅ Clear master file name
Disadvantages:
- ⚠️ Git shows multiple files
- ⚠️ Can confuse new developers
Pattern 3: Tool-Specific Wrappers
# Shared core
vim PROJECT_RULES.md
# Zed wrapper
cat > .rules << 'EOF'
# Zed AI Rules
See PROJECT_RULES.md for complete guidelines.
## Zed-Specific Notes
- Use Agent Panel (cmd-shift-?) for complex refactoring
- Use inline assistant for quick fixes
- Restart Zed after updating PROJECT_RULES.md
EOF
# Cursor wrapper
cat > .cursorrules << 'EOF'
# Cursor Rules
See PROJECT_RULES.md for complete guidelines.
## Cursor-Specific Notes
- Use Composer (cmd-i) for multi-file changes
- Use CMD-K for inline edits
EOF
Advantages:
- ✅ Tool-specific hints
- ✅ Shared core reduces duplication
Disadvantages:
- ⚠️ More files to maintain
- ⚠️ Core rules updates need manual sync
8.3 Migration Helpers
Script: Sync Rules Across Tools
#!/bin/bash
# sync-ai-rules.sh
MASTER="AGENTS.md"
if [ ! -f "$MASTER" ]; then
echo "❌ $MASTER not found"
exit 1
fi
# Create symlinks
ln -sf $MASTER .rules
ln -sf $MASTER .cursorrules
ln -sf $MASTER .windsurfrules
ln -sf $MASTER .clinerules
ln -sf $MASTER CLAUDE.md
# GitHub Copilot
mkdir -p .github
ln -sf ../$MASTER .github/copilot-instructions.md
echo "✅ Synced $MASTER to all tool locations"
Usage:
chmod +x sync-ai-rules.sh
./sync-ai-rules.sh
Pre-Commit Hook:
# .git/hooks/pre-commit
#!/bin/bash
# If AGENTS.md changed, sync symlinks
if git diff --cached --name-only | grep -q "AGENTS.md"; then
echo "📋 AGENTS.md modified, syncing symlinks..."
./sync-ai-rules.sh
git add .rules .cursorrules .windsurfrules
fi
9. Advanced Rule Patterns
9.1 Token Optimization Techniques
Problem: Large rules files consume context window, reducing space for code.
Solution: High-Density Formatting
Before (Low Density — 180 tokens):
When you're writing TypeScript code, it's really important that you make
sure to always include explicit type annotations for all of your function
return types. This helps a lot with maintaining type safety throughout the
entire codebase and it also makes it much easier for other developers to
understand what your functions are supposed to be doing without having to
read through all of the implementation details inside the function body.
After (High Density — 35 tokens):
## TypeScript Rules
- **Required:** Explicit return types on all functions
- **Benefit:** Type safety + readability
- **Example:** `function calc(x: number): number { return x * 2; }`
Savings: 80% token reduction!
Optimization Checklist:
- [ ] Replace prose with bullet points
- [ ] Use tables for mappings/decisions
- [ ] Show code examples instead of explaining
- [ ] Remove filler words ("please", "try to", "it's good to")
- [ ] Use symbols (✅ ❌ ⚠️) instead of words
- [ ] Consolidate repetitive patterns
Table-Based Rules:
## State Management Decision Matrix
| Data Type | Scope | Solution | Example |
|-----------|-------|----------|---------|
| Server data | App | TanStack Query | `useQuery('users')` |
| Form state | Component | React Hook Form | `useForm()` |
| UI state | Component | useState | `const [open, setOpen]` |
| Global client | App | Zustand | `useStore()` |
| URL state | Route | useSearchParams | `const [search]` |
vs Prose (Same Information):
When you need to fetch server data, you should use TanStack Query. For
managing form state, React Hook Form is the right choice. If you just
need simple component-level state like whether a modal is open, useState
works well. For global client state, use Zustand. When state needs to be
reflected in the URL, use Next.js useSearchParams.
Result: Table is 60% fewer tokens with identical information.
9.2 Conditional Guidance Patterns
Zed Limitation: No native conditional loading (unlike Cursor's globs or Roo-Cline's file regex).
Workaround: Inline Conditionals
## Language-Specific Rules
### TypeScript Files (*.ts, *.tsx)
typescript
// TypeScript-specific patterns
### Python Files (*.py)
python
Python-specific patterns
### Rust Files (*.rs)
rust
// Rust-specific patterns
## When to Apply
**AI: Read this section carefully**
- If editing TypeScript/React files → Apply TypeScript rules
- If editing Python files → Apply Python rules
- If editing Rust files → Apply Rust rules
- If editing config files → Ask before major changes
Effectiveness: ~70% (AI often follows, but not guaranteed)
Better Solution: Separate projects with different rules files if languages are completely different.
9.3 Hierarchical Rule Organization
Pattern: XML-Style Semantic Tags
<criticalSecurity>
## Security Requirements (NEVER VIOLATE)
- NEVER commit secrets, API keys, passwords
- ALWAYS validate user inputs (XSS, SQL injection)
- ALWAYS use parameterized queries
- NEVER trust data from external sources
</criticalSecurity>
<codingStandards>
## Code Style (Follow Consistently)
- TypeScript strict mode
- Explicit return types
- Functional components
- Result<T> error handling
</codingStandards>
<bestPractices>
## Recommended Patterns (Use When Applicable)
- Prefer composition over inheritance
- Keep functions under 50 lines
- Extract complex logic to utilities
- Write self-documenting code
</bestPractices>
<optional>
## Optional Optimizations (Nice to Have)
- Memoize expensive calculations
- Use code splitting for large bundles
- Optimize images (Next.js Image component)
</optional>
Benefits:
- Clear priority levels
- Semantic boundaries
- Easy to scan
- AI understands importance hierarchy
9.4 Example-Driven Rules
Most Effective Pattern:
## Rule Name
### ❌ WRONG
typescript
// Anti-pattern code
// Explain specific problems:
// - Problem 1
// - Problem 2
### ✅ CORRECT
typescript
// Recommended pattern
// Explain specific benefits:
// - Benefit 1
// - Benefit 2
### Why This Matters
[1-2 sentences on impact]
Complete Example:
## React State Management
### ❌ WRONG: Prop Drilling
tsx
// App.tsx
function App() {
const [user, setUser] = useState(null);
return ;
}
// Dashboard.tsx
function Dashboard({ user, setUser }: Props) {
return ;
}
// Sidebar.tsx
function Sidebar({ user, setUser }: Props) {
return ;
}
// UserMenu.tsx (finally uses it)
function UserMenu({ user, setUser }: Props) {
return setUser(null)}>Logout;
}
**Problems:**
- Props passed through 3 components that don't use them
- Changing user state interface requires updating 4 files
- Difficult to refactor
- TypeScript boilerplate multiplied
### ✅ CORRECT: Zustand Store
tsx
// stores/userStore.ts
import { create } from 'zustand';
export const useUserStore = create((set) => ({
user: null,
setUser: (user) => set({ user }),
logout: () => set({ user: null }),
}));
// App.tsx
function App() {
return ; // No props!
}
// Dashboard.tsx
function Dashboard() {
return ; // No props!
}
// Sidebar.tsx
function Sidebar() {
return ; // No props!
}
// UserMenu.tsx (consumes directly)
function UserMenu() {
const logout = useUserStore((state) => state.logout);
return Logout;
}
**Benefits:**
- Components only import what they need
- No intermediate prop passing
- Single source of truth
- Easy refactoring
- TypeScript inference automatic
### Why This Matters
Prop drilling is the #1 cause of refactoring pain in React codebases.
Centralized state eliminates this completely.
10. Integration with Agent Panel
10.1 Accessing Agent Panel
Keyboard Shortcut:
- macOS:
cmd-shift-? - Linux/Windows:
ctrl-shift-?
Alternative:
- Click sparkles icon (✨) in top-right corner
First Time Setup:
-
Open Agent Panel (
cmd-shift-?) -
Configure API Key (if not set in environment)
- Click "Configure" or "Settings"
- Enter API key for chosen provider
- Or set environment variable (preferred):
export ANTHROPIC_API_KEY="sk-ant-xxx"
export OPENAI_API_KEY="sk-xxx"
- Restart Zed to load environment variables
- Test: Ask "What are the project rules?"
10.2 How Rules Are Loaded
Loading Sequence:
User Opens Agent Panel
↓
Zed Loads:
1. Model config from .zed/settings.json
2. Rules file (first match in priority order)
3. Current file context (if file open)
↓
Constructs Prompt:
[System Prompt: Entire rules file content]
[Context: Current file or selection]
[User Message: Your request]
↓
Sends to LLM API
↓
Streams Response
↓
User Reviews and Applies
Verification:
## Test Rule Loading
Add this to your `.rules` file:
---
TEST MARKER: If you can read this, rules are loaded correctly.
---
Then ask Agent: "Can you see the test marker in the rules?"
Expected: AI confirms it can see the test marker.
10.3 Effective Prompting Strategies
Strategy 1: Reference Rules Explicitly
❌ Vague:
"Add error handling"
✅ Specific:
"Add error handling using the Result<T> pattern from project rules"
Strategy 2: Request Diffs
❌ Hard to review:
"Refactor this component to use Zustand"
✅ Easy to review:
"Show me a diff for refactoring this component to use Zustand
following project standards"
Strategy 3: Multi-Step with Verification
Step 1: "Based on project rules, what pattern should I use for
fetching user data?"
[AI explains TanStack Query]
Step 2: "Good. Now implement that for fetchUserProfile function."
Strategy 4: Selective Context
With selection:
1. Select specific code block
2. Open Agent Panel
3. Ask: "Refactor this following project standards"
Result: AI focuses only on selection, applies rules
10.4 Agent Panel Workflows
Workflow 1: Feature Implementation
1. Open relevant file (e.g., src/features/user/UserProfile.tsx)
2. Agent Panel: "Based on project rules, create a UserProfile
component that fetches and displays user data"
3. Review generated code:
✓ Check: Uses TanStack Query?
✓ Check: Functional component with TypeScript?
✓ Check: Error handling with Result<T>?
4. Apply or request modifications
5. Generate tests: "Write tests for this component following
project testing standards"
Workflow 2: Refactoring
1. Select code to refactor
2. AgentPanel: "Refactor this selection to use functional patterns
instead of imperative loops"
3. AI suggests:
- Replace `for` loop with `.map()` or `.reduce()`
- Extract helper functions
- Add type annotations
4. Apply changes
Workflow 3: Bug Fixing
1. Select error handling code
2. Agent Panel: "Why is this failing silently? Suggest a fix
that follows our error handling rules."
3. AI identifies missing catch block or incorrect logging
4. Apply fix
11. Performance Optimization
11.1 Token Usage Management
Why It Matters:
- Cost: More tokens = higher API bill
- Speed: More tokens = slower response
- Quality: Context window overflow = AI forgets instructions
Optimization Checklist:
- [ ] Length: Keep
.rulesunder 500 lines (approx 2,500 tokens) - [ ] Density: Use bullet points, not paragraphs
- [ ] Relevance: Remove generic advice ("write clean code")
- [ ] Structure: Use clear headers for easier retrieval
- [ ] Examples: Focus on diffs (bad vs good), not lengthy explanations
Example Optimization:
Before (150 tokens):
When writing TypeScript, it is very important to always use explicit
return types for all functions. This helps with type safety and readability.
Also, please avoid using the 'any' type whenever possible, as it defeats
the purpose of using TypeScript in the first place. Instead, try to use
'unknown' and then narrow the type using type guards.
After (30 tokens):
## TypeScript Rules
- **Required:** Explicit return types on all functions
- **Forbidden:** `any` type (use `unknown` + type guards)
Savings: 80% reduction with identical meaning.
11.2 Context Window Strategy
Prioritize Content:
- Critical Constraints: Tech stack, security, forbidden patterns (Top 20%)
- Common Patterns: Component structure, error handling (Middle 50%)
- Edge Cases: Known issues, specific workarounds (Bottom 30%)
If Rules Exceed Context Window:
Strategy 1: Split by Project
- Frontend-only repo with frontend rules
- Backend-only repo with backend rules
Strategy 2: Reference External Docs
- Keep critical rules in
.rules - Link to full documentation (AI won't read, but humans will)
Strategy 3: Use Universal Standard (AGENTS.md)
- If using multiple tools, optimize one file for all contexts
12. Troubleshooting and Debugging
12.1 Rules Not Loading
Symptoms:
- AI ignores project standards
- AI gives generic answers
- Test marker not found
Diagnostic Checklist:
-
File Name: Is it exactly
.rules? (No extension, case sensitive) -
Location: Is it in the project root? (Not in
.zed/orsrc/) -
Priority: Are there other files? (e.g.,
.cursorrulesor.windsurfrules)- Zed loads first match only
- Run
ls -lato check for conflicts
- Content: Is it valid Markdown?
-
Restart: Did you reload Zed after creating the file?
-
cmd-shift-p→zed: reload window
-
Fix:
# Ensure only one primary rule file
rm .cursorrules .windsurfrules 2>/dev/null
mv my-rules.md .rules
12.2 AI Ignoring Specific Rules
Symptoms:
- File loaded, but AI ignores "No
anytype" rule - AI generates class components instead of functional
Diagnostic Checklist:
-
Specificity: Is the rule specific enough?
- ❌ "Write good TypeScript"
- ✅ "FORBIDDEN:
anytype. REQUIRED: Explicit return types."
-
Examples: Did you provide a code example?
- Rules with examples have 3.5x higher adherence
-
Contradictions: Are there conflicting rules?
- Use "Violation Prompt" (Section 6.2.2) to check
-
Placement: Is the rule buried?
- Move critical rules to the top
- Use XML tags (
<CRITICAL>) for emphasis
Fix:
<CRITICAL>
## TypeScript Rules (STRICT ENFORCEMENT)
- ❌ NEVER use `any`
- ✅ ALWAYS use `unknown` + validation
</CRITICAL>
12.3 Model Issues
Symptoms:
- "API key missing" error
- Slow responses
- Low-quality code
Diagnostic Checklist:
-
API Key: Is
ANTHROPIC_API_KEYorOPENAI_API_KEYset?- Check:
echo $ANTHROPIC_API_KEYin terminal - Restart Zed to load env vars
- Check:
-
Model Selection: Is the correct model configured?
- Check
.zed/settings.json
- Check
-
Quota: Are you out of API credits?
- Check provider dashboard
Fix:
# Re-export keys
export ANTHROPIC_API_KEY="sk-ant-new-key"
export OPENAI_API_KEY="sk-new-key"
# Restart Zed
12.4 Debugging with Agent
Prompt to Debug Rules:
Review the loaded system prompt and rules.
1. Do you see a section called "Testing Requirements"?
2. What is the required test coverage?
3. Are there any contradictions in the rules?
Expected Response:
- "Yes, I see the Testing Requirements section."
- "Coverage is set to 80%."
- "No contradictions found."
If AI fails: Rules file is not loaded correctly. Check filename/location.
13. Production Examples by Tech Stack
13.1 React + TypeScript (Frontend)
# Frontend Rules
## Tech Stack
- React 19, TypeScript 5.4, Tailwind CSS 4.0
- Vite, Vitest, React Testing Library
## Coding Standards
### Component Structure
tsx
// ✅ Functional, typed props
interface Props {
label: string;
onClick: () => void;
}
export function Button({ label, onClick }: Props) {
return (
onClick={onClick}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
{label}
);
}
### Hooks
- Use custom hooks for logic extraction
- Rules of Hooks: Top level only, no loops/conditions
### State
- Local: `useState`
- Global: `Zustand` (no Redux)
- Server: `TanStack Query`
## Testing
- Unit test logical hooks
- Component test interactions
- 80% coverage
13.2 Python FastAPI (Backend)
# Backend Rules
## Tech Stack
- Python 3.12, FastAPI 0.110
- PostgreSQL 16, SQLAlchemy 2.0 (Async)
- Pydantic 2.0 for validation
## Coding Standards
### Type Hints
python
✅ REQUIRED: Full type hints
async def get_user(user_id: int) -> UserResponse:
...
❌ FORBIDDEN: Missing types
async def get_user(user_id):
...
### Async Database
python
✅ Use async session
async with async_session() as session:
result = await session.execute(select(User))
### Error Handling
- Raise `HTTPException` for API errors
- Log exceptions before raising
- Use custom exception classes
## Testing
- Use `pytest` and `pytest-asyncio`
- Fixtures for database state
- Mock external services
13.3 Rust (Systems)
# Rust Rules
## Tech Stack
- Rust 1.78 (2021 edition)
- Tokio (async runtime)
- Axum (web framework)
- SQLx (database)
## Coding Standards
### Error Handling
- Use `Result<T, E>` everywhere
- Use `thiserror` for library errors
- Use `anyhow` for application errors
- No `.unwrap()` in production code (use `?` or `.expect()`)
### Async
- Use `#[tokio::main]`
- Prefer async traits where applicable
### Clippy
- Code must pass `cargo clippy -- -D warnings`
- No `allow(clippy::all)`
## Testing
- Unit tests in same file (`mod tests`)
- Integration tests in `tests/` directory
- Doc tests for public API
14. Migration from Other Tools
14.1 From Cursor
Step 1: Locate Rules
- Find
.cursorrulesor.cursor/rules/*.mdc
Step 2: Convert
- If
.cursorrules: Rename to.rules(or keep as is, Zed reads it) - If
.cursor/rules/*.mdc: Concatenate into single.rulesfile
# Combine MDC files
cat .cursor/rules/*.mdc > .rules
# Remove YAML frontmatter manually
# (Zed ignores it, but cleaner to remove)
Step 3: Verify
- Open Zed Agent Panel
- Ask: "What rules do you see?"
14.2 From GitHub Copilot
Step 1: Locate Rules
- Find
.github/copilot-instructions.md
Step 2: Symlink or Copy
# Option A: Symlink (keeps Copilot working)
ln -s .github/copilot-instructions.md .rules
# Option B: Copy
cp .github/copilot-instructions.md .rules
Step 3: Verify
- Copilot rules are standard Markdown, so they work immediately in Zed.
14.3 From VS Code (General)
Step 1: Extract Settings
- Identify key settings in
.vscode/settings.json - Map to
.zed/settings.json
Mapping Table:
| VS Code Setting | Zed Equivalent |
|---|---|
editor.fontSize |
buffer_font_size |
editor.fontFamily |
buffer_font_family |
editor.formatOnSave |
format_on_save |
editor.tabSize |
tab_size |
files.exclude |
file_scan_exclusions |
Step 2: Create Rules
- If no previous rules, create
.rulesfrom template (Section 4.1)
Conclusion
Zed's AI configuration is elegantly simple:
-
.zed/settings.jsonfor machine config (models, editor) -
.rulesfor human instructions (Markdown)
By separating these concerns, Zed provides a flexible, portable, and powerful environment for AI-assisted development. Focus on writing high-quality, example-driven Markdown rules, and Zed's Agent Panel will handle the rest.
Top comments (0)