Project-Specific Rules
Make diffray even smarter by teaching it your team's standards.
Your Rules, Your Way
diffray comes with comprehensive default rules, but every team is different:
- Your coding standards — enforce conventions specific to your team
- Your libraries — ensure correct usage of internal APIs
- Your domain — add checks that make sense for your business
How It Works
- Add a
.diffray/rules/folder to your repository - Create YAML files with your custom rules
- diffray automatically picks them up on the next PR
your-repo/
└── .diffray/
└── rules/
└── team-standards.yaml
Example: Enforce Your Logger
rules:
- id: use_internal_logger
agent: quality
title: "Use internal logger"
description: "Use our logger instead of console for proper log levels"
importance: 7
match:
file_glob:
- "src/**/*.ts"
- "!src/**/*.test.ts"
checklist:
- "Find console.log/error/warn calls"
- "Suggest using logger from @/lib/logger"
examples:
bad: |
console.log('User logged in', userId);
good: |
logger.info('User logged in', { userId });
Example: Rule for Specific Path
Apply rules only to certain folders — like checking API endpoints only in your API directory:
rules:
- id: api_error_handling
agent: bugs
title: "API endpoints must handle errors"
description: "All API routes should have try-catch with proper error responses"
importance: 8
match:
file_glob:
- "src/api/**/*.ts" # Only API folder
- "src/routes/**/*.ts" # Or routes folder
- "!src/api/**/*.test.ts" # Exclude tests
checklist:
- "Check that async handlers have try-catch"
- "Verify error responses use standard format"
examples:
bad: |
app.get('/users', async (req, res) => {
const users = await db.getUsers();
res.json(users);
});
good: |
app.get('/users', async (req, res) => {
try {
const users = await db.getUsers();
res.json(users);
} catch (error) {
res.status(500).json({ error: 'Failed to fetch users' });
}
});
What You Can Customize
| What | How |
|---|---|
| Add new rules | Create rules for your specific patterns |
| Adjust severity | Make certain checks more or less strict |
| Target specific folders | Apply rules only where they matter |
| Disable default rules | Use config.yaml to exclude rules |
Using Tags
Tags help categorize rules and can be used for filtering. Add one or more tags to your rules:
rules:
- id: use_internal_logger
agent: quality
title: "Use internal logger"
# ...
tags:
- logging
- typescript
- maintainability
Available Tags
| Category | Tags |
|---|---|
| Core | security, performance, bugs, error-handling, maintainability, readability, quality, consistency |
| Code quality | style-conventions, type-safety, duplication, dead-code, code-quality, debugging, memory, memory-leak |
| Architecture | architecture, api-design, api, api-contracts-versioning, separation-of-concerns, testability |
| Testing & docs | testing, testing-quality, documentation, docstring, docs-adrs, e2e, mocha, chai, sinon |
| Observability | logging, observability, traceability |
| Compliance | compliance-gdpr, compliance-soc2-essentials, compliance-pci-dss, compliance-hipaa, compliance-lgpd, privacy-pii, secrets, secrets-credentials |
| Languages | typescript, javascript, python, go, java, kotlin, csharp, rust, ruby, php, dart, swift, scala, cpp, c, shell, graphql, protobuf, solidity, css |
| Frameworks | react, nextjs, vue, angular, svelte, nestjs, nodejs, django, fastapi, flask, spring, rails, aspnet, dotnet, wordpress |
| Stacks | stack-nextjs, stack-nodejs, stack-php, stack-python, stack-react, stack-vue |
| Infrastructure | docker, kubernetes, ci-cd-build-hygiene, infra-as-code, infrastructure, monorepo-hygiene, container-docker-hygiene |
| Frontend | frontend, dom, a11y, accessibility, accessibility-a11y, i18n, internationalization-i18n, state-management, design-system, ui-robustness, ux, bundle-size, web-static-assets |
| Async & Concurrency | async, concurrency, race-condition, resilience, resilience-retries-idempotency, idempotency |
| Data & APIs | caching-strategy, migrations-backward-compat, dependency-supply-chain, financial, payments, inventory |
| Git & Deployment | git, deployment, risk-management, build-tools |
| Miscellaneous | owasp, prototype-pollution, organization, server-actions, server-components, vite |
Assigning Rules to Agents
Each rule is processed by a specialized agent. Choose the one that fits:
security— vulnerabilities, auth, data exposureperformance— bottlenecks, efficiencybugs— logic errors, runtime issuesquality— readability, best practicesarchitecture— design patterns, structureconsistency— code reuse, conventionsdocumentation— docs and commentstesting— test quality and coveragegeneral— cross-cutting concerns
Example: Feature Flags
If your team uses a specific feature flag library, create a rule to enforce proper usage patterns:
rules:
- id: feature_flag_gradual_rollout
agent: quality
title: "Feature flags should support gradual rollout"
description: "Risky changes should use percentage-based rollout via feature flags"
importance: 7
match:
file_glob:
- "src/**/*.ts"
- "src/**/*.js"
- "!src/**/*.test.ts"
content_regex:
- "featureFlags\\."
- "isFeatureEnabled"
checklist:
- "Check if feature flag supports percentage-based activation"
- "Verify user/company ID is passed for consistent rollout"
- "Ensure new risky features are behind feature flags"
examples:
bad: |
// No gradual rollout support
if (featureFlags.isEnabled('new_checkout')) {
useNewCheckout();
}
// Boolean only - can't do percentage rollout
const useNew = config.newCheckoutEnabled;
good: |
// Percentage-based rollout with user context
if (featureFlags.isEnabled('new_checkout', {
userId: user.id, // Consistent per-user experience
percent: 10, // Enable for 10% of users
allowlist: ['beta-testers'] // Always enable for beta group
})) {
useNewCheckout();
}
tags:
- quality
- architecture
- deployment
why_important: Gradual rollout reduces blast radius and enables quick rollback.
Example: Domain-Specific Validation
Enforce business rules specific to your domain:
rules:
- id: money_use_decimal
agent: bugs
title: "Use Decimal for monetary values"
description: "Never use float/number for money - use Decimal or BigInt cents"
importance: 9
match:
file_glob:
- "src/**/*.ts"
- "src/**/*.py"
content_regex:
- "(price|amount|total|cost|fee|balance)\\s*[=:]\\s*\\d+\\.\\d+"
- "(price|amount|total|cost|fee|balance)\\s*:\\s*(number|float)"
checklist:
- "Find monetary fields using float/number types"
- "Check calculations don't use floating point arithmetic"
- "Verify storage uses cents (integer) or Decimal type"
examples:
bad: |
// TypeScript - float precision issues
interface Order {
price: number; // 0.1 + 0.2 !== 0.3 in JS!
total: number;
}
const total = price * quantity; // Floating point errors
# Python - same problem
price: float = 19.99
total = price * quantity # Precision loss
good: |
// TypeScript - use cents (integer)
interface Order {
priceInCents: number; // Store as integer cents
totalInCents: number;
}
const totalCents = priceInCents * quantity;
const displayPrice = (totalCents / 100).toFixed(2);
// Or use a Decimal library
import Decimal from 'decimal.js';
const price = new Decimal('19.99');
const total = price.times(quantity);
# Python - use Decimal
from decimal import Decimal
price = Decimal('19.99')
total = price * quantity
tags:
- bugs
- fintech
- data-integrity
why_important: Floating point errors in money calculations cause real financial discrepancies.
Example: Internal API Usage
Ensure your internal libraries are used correctly:
rules:
- id: http_client_use_internal
agent: consistency
title: "Use internal HTTP client wrapper"
description: "Use our httpClient instead of raw fetch/axios for consistent error handling"
importance: 7
match:
file_glob:
- "src/**/*.ts"
- "!src/lib/http-client.ts" # Exclude the wrapper itself
- "!src/**/*.test.ts"
content_regex:
- "\\bfetch\\("
- "axios\\."
- "import.*from ['\"]axios['\"]"
checklist:
- "Find raw fetch() or axios calls"
- "Check if code should use httpClient from @/lib/http-client"
- "Verify error handling follows team standards"
examples:
bad: |
// Raw fetch - no centralized error handling
const response = await fetch('/api/users');
const data = await response.json();
// Direct axios - bypasses our interceptors
import axios from 'axios';
const { data } = await axios.get('/api/users');
good: |
// Use internal wrapper with built-in:
// - Auth token injection
// - Error normalization
// - Retry logic
// - Request logging
import { httpClient } from '@/lib/http-client';
const data = await httpClient.get('/api/users');
tags:
- consistency
- error-handling
- internal-api
why_important: Centralized HTTP client ensures consistent auth, logging, and error handling.
Tips for Great Rules
- Start simple — one or two rules, see how they work
- Be specific — target only relevant files
- Add examples — show what's wrong and how to fix it
- Test it — create a PR that should trigger your rule
See also:
- Configuration — global settings, file filters, rule exclusions
Need help writing rules? Contact support and we'll help you set up rules for your team's needs.