Context Injection: Teaching AI Domain Knowledge
Master context injection techniques to teach Claude domain-specific knowledge. Learn to inject conventions, rules, and expertise effectively.
Master context injection techniques to teach Claude domain-specific knowledge. Learn to inject conventions, rules, and expertise effectively.
Claude knows a lot, but Claude does not know your project, your conventions, your domain-specific rules, or your team's preferences. Context injection bridges this gap by embedding the knowledge Claude needs directly into skills.
Effective context injection transforms Claude from a general assistant into a domain expert who understands your specific environment. This guide covers context injection techniques, what to inject, and how to structure injected knowledge.
Without context injection:
User: "Review this API endpoint"
Claude: Generic API advice based on general best practices
With context injection:
User: "Review this API endpoint"
Claude: Review based on YOUR API conventions, error formats,
authentication patterns, and team standards
The skill provides the domain knowledge that makes Claude effective in your environment.
1. Conventions How your team does things:
2. Domain Rules Business or technical requirements:
3. Expertise Specialized knowledge:
4. Environment Your specific setup:
## Naming Conventions
### Files and Directories
- Components: PascalCase (UserProfile.tsx)
- Utilities: camelCase (formatDate.ts)
- Constants: UPPER_SNAKE_CASE in constants.ts
- Tests: [name].test.ts alongside source
### Functions
- Action functions: verb + noun (getUserById, createOrder)
- Boolean functions: is/has/can prefix (isValid, hasPermission)
- Transformation: to + type (toJSON, toString)
- Event handlers: on + event (onClick, onSubmit)
### Variables
- Boolean: is/has/can prefix (isLoading, hasError)
- Arrays: plural nouns (users, orderItems)
- Counts: noun + Count (userCount, retryCount)
- Maps/Objects: singular noun (userById, configByEnv)
### Examples
Good:
```typescript
const isUserActive = user.status === 'active';
const getUsersByDepartment = async (deptId: string) => {...};
const orderCount = orders.length;
Bad:
const active = user.status === 'active'; // Missing prefix
const getUser = async (id) => {...}; // Not descriptive
const num = orders.length; // Unclear meaning
### Code Organization
```markdown
## Project Structure
src/ ├── api/ # API client and request handling │ ├── client.ts # Base API client configuration │ ├── endpoints/ # Endpoint-specific modules │ └── types/ # API request/response types ├── components/ # Reusable UI components │ ├── common/ # Generic components (Button, Input) │ ├── features/ # Feature-specific components │ └── layouts/ # Page layout components ├── hooks/ # Custom React hooks ├── pages/ # Next.js page components ├── services/ # Business logic layer ├── stores/ # State management (Zustand) ├── types/ # Shared TypeScript types └── utils/ # Pure utility functions
### Placement Rules
**API types go in api/types/, not global types/**
- Request types: `Create[Entity]Request`
- Response types: `[Entity]Response`
**Components:**
- Reused 3+ times → components/common/
- Feature-specific → components/features/[feature]/
- Page layouts → components/layouts/
**Hooks:**
- Generic → hooks/
- Feature-specific → features/[feature]/hooks/
## Documentation Conventions
### Function Documentation
Use JSDoc with TypeScript types:
```typescript
/**
* Fetches user by ID with optional profile expansion.
*
* @param userId - Unique user identifier
* @param options - Fetch options
* @returns User data or null if not found
* @throws {ApiError} When API request fails
*
* @example
* const user = await getUser('123', { includeProfile: true });
*/
async function getUser(
userId: string,
options?: GetUserOptions
): Promise<User | null> {
// ...
}
/**
* User avatar with status indicator.
*
* @example
* <UserAvatar user={currentUser} size="lg" showStatus />
*/
interface UserAvatarProps {
/** User object containing avatar URL and name */
user: User;
/** Avatar size: sm (24px), md (32px), lg (48px) */
size?: 'sm' | 'md' | 'lg';
/** Whether to show online/offline status dot */
showStatus?: boolean;
}
## Injecting Domain Rules
### Business Rules
```markdown
## Order Processing Rules
### Order States
1. `draft` - Created, not submitted
2. `pending` - Submitted, awaiting approval
3. `approved` - Approved, ready for fulfillment
4. `processing` - Being fulfilled
5. `shipped` - In transit
6. `delivered` - Received by customer
7. `cancelled` - Order cancelled
### State Transitions
draft → pending (submit) pending → approved (approve) | cancelled (cancel) approved → processing (start_fulfillment) | cancelled (cancel) processing → shipped (ship) | cancelled (cancel with restock) shipped → delivered (confirm_delivery)
### Business Constraints
**Orders cannot be cancelled after shipping**
- Once shipped, cancellation requires return process
- System should reject cancel requests for shipped orders
**Approval thresholds**
- Orders < $500: Auto-approved
- Orders $500-$5000: Manager approval required
- Orders > $5000: Director approval required
**Inventory rules**
- Cannot approve order if insufficient stock
- Backorder allowed only for approved suppliers
- Overselling prevention: Lock inventory on approval
## Input Validation
### User Registration
```typescript
const userSchema = {
email: {
required: true,
format: 'email',
maxLength: 255,
unique: true, // Check against database
},
password: {
required: true,
minLength: 12,
requireUppercase: true,
requireLowercase: true,
requireNumber: true,
requireSpecial: true,
notContains: ['password', '123456', 'qwerty'],
},
name: {
required: true,
minLength: 2,
maxLength: 100,
pattern: /^[a-zA-Z\s'-]+$/,
},
phone: {
required: false,
format: 'e164', // +1234567890
},
};
{
"error": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Email must be a valid email address"
},
{
"field": "password",
"code": "TOO_SHORT",
"message": "Password must be at least 12 characters"
}
]
}
### Security Requirements
```markdown
## Security Standards
### Authentication
- JWT tokens with 15-minute expiry
- Refresh tokens: 7-day expiry, single use
- Token rotation on refresh
- Immediate invalidation on logout (blocklist)
### Authorization
- Role-based access control (RBAC)
- Resource-level permissions where applicable
- Deny by default, explicit allow required
- Audit log for sensitive operations
### Data Protection
- PII must be encrypted at rest (AES-256)
- TLS 1.3 required for all external communication
- API keys never in logs or responses
- Passwords: Argon2id with appropriate parameters
### Code Patterns
**Always use:**
```typescript
// Parameter binding for SQL
const users = await db.query(
'SELECT * FROM users WHERE id = $1',
[userId]
);
// Rate limiting for public endpoints
@RateLimit({ points: 100, duration: 60 })
async function publicEndpoint() {...}
// Input validation before processing
const validated = schema.parse(input);
Never:
## Injecting Expertise
### Domain Terminology
```markdown
## Healthcare Domain Terminology
### Common Abbreviations
- PHI: Protected Health Information
- EMR: Electronic Medical Record
- EHR: Electronic Health Record (interoperable)
- HIPAA: Health Insurance Portability and Accountability Act
- HL7: Health Level 7 (messaging standard)
- FHIR: Fast Healthcare Interoperability Resources
### HIPAA Identifiers (The 18)
PHI includes any of these identifiers:
1. Names
2. Geographic data smaller than state
3. Dates (except year) related to individual
4. Phone numbers
5. Fax numbers
6. Email addresses
7. Social Security numbers
8. Medical record numbers
9. Health plan numbers
10. Account numbers
11. Certificate/license numbers
12. Vehicle identifiers
13. Device identifiers
14. Web URLs
15. IP addresses
16. Biometric identifiers
17. Full-face photos
18. Any unique identifier
### Data Handling Rules
- PHI must never appear in logs
- De-identification requires removing all 18 identifiers
- Minimum necessary: Only access/share what is required
- Audit trail required for all PHI access
## React Performance Patterns
### When to Memoize
**Use useMemo when:**
- Expensive calculations that do not need to run every render
- Values passed to children that would cause re-renders
- Dependencies are stable (primitives, memoized objects)
**Skip useMemo when:**
- Calculation is trivial
- Component rarely re-renders
- Value is only used locally
### Common Patterns
**Stable callbacks:**
```typescript
// Do: Memoize callbacks passed to children
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
// Don't: Create new function every render for memoized children
<MemoizedChild onClick={() => doSomething(id)} />
Derived state:
// Do: Compute during render
const sortedItems = useMemo(
() => items.sort((a, b) => a.name.localeCompare(b.name)),
[items]
);
// Don't: Store derived state
const [sortedItems, setSortedItems] = useState([]);
useEffect(() => {
setSortedItems(items.sort(...));
}, [items]);
Creating objects in render
// Bad: New object every render
<Child style={{ color: 'red' }} />
// Good: Stable reference
const style = useMemo(() => ({ color }), [color]);
<Child style={style} />
Fetching in useEffect without cleanup
// Bad: Race condition possible
useEffect(() => {
fetchData().then(setData);
}, [id]);
// Good: Cancel stale requests
useEffect(() => {
let cancelled = false;
fetchData().then(d => !cancelled && setData(d));
return () => { cancelled = true; };
}, [id]);
### Historical Context
```markdown
## Architecture Decision Records
### ADR-001: Monolithic Architecture
**Date:** 2023-01-15
**Status:** Accepted
**Context:**
Starting a new project with a team of 4 developers.
Microservices considered but rejected.
**Decision:**
Build as a modular monolith with clear boundaries.
**Rationale:**
- Team too small for microservice overhead
- Domain boundaries not yet clear
- Deployment simplicity critical for velocity
- Can extract services later if needed
**Consequences:**
- All code in single repository
- Shared database with module-specific schemas
- Internal APIs between modules for future extraction
---
### ADR-002: PostgreSQL over MySQL
**Date:** 2023-01-20
**Status:** Accepted
**Context:**
Choosing primary database for the application.
**Decision:**
Use PostgreSQL 15.
**Rationale:**
- JSONB support for flexible data (user preferences, settings)
- Better concurrent write handling (MVCC)
- Rich indexing options (GIN, GiST)
- Team experience with PostgreSQL
**Consequences:**
- Some MySQL-specific features unavailable
- Slightly steeper learning curve for new hires
- Better long-term flexibility
Structure from general to specific:
# API Development Skill
## Level 1: Universal Principles
REST principles, HTTP semantics, security basics.
Always applicable.
## Level 2: Company Standards
Our API versioning strategy, authentication patterns,
error format. Applicable to all our APIs.
## Level 3: Project Specifics
This project's endpoints, data models, integrations.
Specific to current context.
## Context Organization
### Must Know (Always Applied)
Critical information that applies to every interaction:
- Security requirements
- Naming conventions
- Error handling patterns
### Should Know (Applied When Relevant)
Important context that applies to specific scenarios:
- Specific module structures
- Integration patterns
- Performance considerations
### Reference (Looked Up When Needed)
Detailed information for specific questions:
- Complete API schemas
- Full configuration options
- Detailed examples
Mark context that might become stale:
## Dependencies (Last Updated: 2025-01-15)
Current production versions:
- Node.js: 20.10 LTS
- TypeScript: 5.3
- React: 18.2
- Next.js: 14.1
**Note:** Verify current versions before dependency-related advice.
This context may be outdated.
Define terms at the start:
## Glossary
| Term | Meaning |
|------|---------|
| Widget | A configurable dashboard component |
| Canvas | The drag-and-drop layout editor |
| Blueprint | A saved widget configuration |
| Palette | The available widgets list |
When these terms appear, use their specific meanings
as defined above, not general meanings.
Teach through examples:
## API Response Format
**Correct:**
```json
{
"data": {
"user": { "id": "123", "name": "Alice" }
},
"meta": {
"requestId": "abc-123"
}
}
Incorrect:
{
"user": { "id": "123", "name": "Alice" }
}
All responses must include the wrapper structure with
data and meta fields.
### The Constraint Pattern
Define what must and must not happen:
```markdown
## Immutable Constraints
### Always
- Include request ID in logs
- Validate input before processing
- Return consistent error format
### Never
- Log sensitive data (passwords, tokens, PII)
- Return stack traces to clients
- Bypass rate limiting for any user
Not everything needs injection. Prioritize:
Verbose:
When you are writing code, you should always make sure
to use two spaces for indentation instead of tabs or
four spaces because our team has standardized on two
spaces for all of our JavaScript and TypeScript files.
Compressed:
Indentation: 2 spaces (JS/TS files)
Same information, fraction of the tokens.
For large context:
## API Schema
See `/docs/openapi.yaml` for complete API specification.
Key endpoints for common tasks:
- User CRUD: /api/v1/users
- Orders: /api/v1/orders
- Inventory: /api/v1/inventory
Reference the OpenAPI spec for parameter details.
Do not paste the entire schema into the skill.
Context injection transforms Claude from a general assistant into a specialist who understands your environment. Effective context injection:
The goal is providing exactly the knowledge Claude needs to be effective in your specific domain, no more and no less.
Ready to design consistent skill outputs? Continue to Structured Output Design for Predictable Results for output format mastery.
This skill provides a structured workflow for guiding users through collaborative document creation. Act as an active guide, walking users through three stages: Context Gathering, Refinement & Structu