Your AI Context Is Locked to One Tool. Here's How to Fix It.
Cursor rules, Claude instructions, Codex agents: every AI tool wants its own config. A practical guide to writing project context once and generating it for every platform.
You've spent hours tuning Cursor with rules, skills, and custom agents. Your AI finally understands your project. Then you try Claude Code. Or Codex. Or Gemini.
None of your context carries over. You're starting from zero.
TL;DR Every AI coding tool wants its own config format: Cursor uses
.mdcfiles, Claude readsCLAUDE.md, Codex readsAGENTS.md. Write your project context once in canonical files under.context/and.agents/skills/, then generate the per-tool configs with a shell script. Use JSON schemas to validate structured contracts, like work orders and verification reports, consistently across every tool.
The Fragmentation Problem
Five AI coding tools. Five config formats. Zero interoperability.
| Tool | Config File | Format |
|---|---|---|
| Cursor | .cursor/rules/*.mdc | Markdown + YAML frontmatter |
| Claude Code | CLAUDE.md | Plain markdown |
| Codex CLI | AGENTS.md | Plain markdown |
| GitHub Copilot | .github/copilot-instructions.md | Plain markdown |
| Windsurf | .windsurfrules | Plain markdown |
If you maintain all five, they will drift. You'll update a safety boundary in one file and forget the others. Now your Claude agent can push to main but your Cursor agent can't. Same project, different rules.
This isn't hypothetical. I hit it on my own site: I had Cursor rules, skills, and agents that worked perfectly, but they were all in .cursor/ which is invisible to every other tool.
Single Source of Truth
The fix is the same principle we use in code: don't repeat yourself.
Write your project context once in a canonical location. Generate tool-specific configs from it.
SurfContext (ARDS v3.0) is an open standard that defines this pattern, and the design principles behind everything in this post.
ARDS Design Principles (from the spec)
- Single source of truth: each fact lives in one file. Other files reference it, never duplicate it.
- Canonical source, generated output: edit
.context/. Never edit generated files directly. - Tables over prose: AI agents parse structured data faster. Use tables for any data with 2+ attributes.
- Token budget awareness: root context loads every turn. Everything else loads on demand.
The core idea:
| Canonical (you edit these) | Generated (script produces these) | |
|---|---|---|
CONTEXT.md | → | CLAUDE.md, AGENTS.md |
.context/docs/*.md | → | .cursor/rules/*.mdc |
.context/agents/*.md | → | .cursor/agents/*.md |
.context/ai-ignore-patterns.md | → | .cursorignore |
.agents/skills/*/SKILL.md | None (tool-agnostic, no generation needed) |
flowchart LR
subgraph canonical ["Canonical (you edit)"]
CONTEXT[CONTEXT.md]
Docs[.context/docs/]
Agents[.context/agents/]
Ignore[ai-ignore-patterns.md]
end
subgraph generated ["Generated (script produces)"]
CLAUDE[CLAUDE.md]
AGENTSMD[AGENTS.md]
Rules[.cursor/rules/*.mdc]
CursorAgents[.cursor/agents/]
Cursorignore[.cursorignore]
end
CONTEXT --> CLAUDE
CONTEXT --> AGENTSMD
Docs --> Rules
Agents --> CursorAgents
Ignore --> CursorignoreThe file structure
project/
CONTEXT.md # Root context (single source of truth)
surfcontext.json # Platform targeting config
.context/
docs/ # Knowledge docs (rules content)
agents/ # Agent definitions
schemas/ # JSON schemas for contracts
ai-ignore-patterns.md # What to exclude from AI context
.agents/skills/ # Tool-agnostic skills (open standard)
work-order/SKILL.md
deploy-verify/SKILL.md
.cursor/rules/*.mdc # Generated for Cursor
CLAUDE.md # Generated for Claude
AGENTS.md # Generated for Codex
Why .agents/skills/ for skills?
Agent Skills is an open standard (originally from Anthropic) that Cursor, Claude, and Codex all support. They all load from .agents/skills/. No generation needed. Put your skills there once, every tool finds them.
JSON Schemas for Contracts
Here's a problem most people don't think about: when an AI agent produces a work order or a verification report, how do you know the output is consistent?
If you define a work order as "goal, non-goals, constraints, acceptance criteria" in a markdown template, nothing enforces that structure. An agent might skip non-goals, rename fields, or add extra sections.
JSON schemas fix this. Define the contract once, validate against it.
work-order.schema.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Work Order",
"type": "object",
"required": ["goal", "nonGoals", "constraints",
"acceptanceCriteria", "context"],
"properties": {
"goal": {
"type": "array",
"items": { "type": "string" },
"minItems": 1
},
"nonGoals": {
"type": "array",
"items": { "type": "string" }
},
"constraints": {
"type": "array",
"items": { "type": "string" }
},
"acceptanceCriteria": {
"type": "array",
"items": { "type": "string" }
},
"context": {
"type": "array",
"items": { "type": "string" },
"maxItems": 5
}
}
}
Now any agent (Cursor, Claude, Codex) that produces a work order can be validated against the same schema. If a field is missing, you catch it immediately.
The Generation Script
A simple shell script bridges canonical and generated:
- Root context: copy
CONTEXT.md→CLAUDE.mdandAGENTS.mdwith a "do not edit" header. - Rules: for each
.context/docs/*.md, emit.cursor/rules/*.mdcwith Cursor-specific YAML frontmatter. - Agents: copy
.context/agents/*.md→.cursor/agents/*.md. - Ignore patterns: extract patterns from
.context/ai-ignore-patterns.md→.cursorignore.
Every generated file gets a header:
<!-- Generated from .context/, do not edit.
Run ./scripts/generate-ai-context.sh to update. -->
This prevents the most common failure mode: someone edits a generated file directly, then the next generation run overwrites their changes.
Practical Migration
If you already have Cursor rules and want to go tool-agnostic:
- Create CONTEXT.md: merge your AGENTS.md and always-on rules into a single root context file. Use tables over prose: AI agents parse structured data faster.
- Move rules to
.context/docs/: strip Cursor-specific frontmatter (globs, alwaysApply). Keep the content as pure markdown. The generation script adds frontmatter back for Cursor. - Move skills to
.agents/skills/: the Agent Skills standard is supported by Cursor, Claude, and Codex. No generation step needed. - Add schemas and generation script: define JSON schemas for your contracts. Write a generation script that produces tool-specific files from canonical sources.
- Commit everything: both canonical and generated files. Remove
.cursor/from.gitignore. Anyone cloning the repo gets working AI context for any tool.
The No-Contradiction Rule
The hardest part isn't the file structure: it's making sure canonical and generated files never contradict each other.
| Layer | Canonical (edit here) | Generated (do not edit) |
|---|---|---|
| Root context | CONTEXT.md | AGENTS.md, CLAUDE.md |
| Rules | .context/docs/*.md | .cursor/rules/*.mdc |
| Skills | .agents/skills/*/SKILL.md | None |
| Agents | .context/agents/*.md | .cursor/agents/*.md |
| Ignore patterns | .context/ai-ignore-patterns.md | .cursorignore |
Three safeguards:
- Generated file headers: every generated file starts with "do not edit", so anyone opening the file knows immediately.
- Full overwrite: the generation script replaces files entirely. Manual edits don't survive the next run.
- Validation script: checks that canonical files exist, JSON is valid, and generated files have the expected header.
The Bottom Line
AI tools will keep fragmenting. New ones will appear, each with their own config format. The only sustainable approach is to write your context once and generate the rest.
It takes about 30 minutes to set up. After that, switching between Cursor, Claude, and Codex is just running a script.