I set up Claude Code on this blog’s own repo - a root CLAUDE.md, a .claude/rules/ directory, skills under .claude/skills/ - and ended up cross-referencing it against the equivalent GitHub Copilot setup I’d built on a CDK project. Copilot centralises everything under .github/ and scopes by path through frontmatter. Claude Code works the opposite way: it walks the directory tree from wherever you launch it, loading any CLAUDE.md it finds along the way.
Here’s the order I’d actually set it up in, from a blank repo.
1. Create the root CLAUDE.md
CLAUDE.md (or .claude/CLAUDE.md) at the project root is the file every session loads in full at launch - no setting to enable, no reference needed in chat. It’s the same project this blog’s Copilot post used as an example, written for Claude Code instead:
# Project name
AWS CDK v2 (Python) infrastructure. `app.py` registers all stacks.
## Conventions
- Stack and construct IDs use PascalCase; file names use snake_case
- Every stack takes `env` and `config` as constructor arguments
- Tag every stack with `Environment` and `Owner`
## Adding a new stack
1. Create `cdk_app/<area>/<name>_stack.py`
2. Register it in `app.py`
3. Add a README entry under `cdk_app/<area>/`
## Deploying
Run `cdk deploy --require-approval never -c env=dev` from the project root.
Run /init from a session in the project root to generate a starting version automatically - Claude analyses the codebase and writes build commands, test instructions, and conventions it can detect on its own. Refine from there with anything it couldn’t discover by reading the code.
Keep it under 200 lines. CLAUDE.md content is delivered as a user message, not the system prompt, so it competes with the rest of the conversation for context - longer files consume more of it and measurably reduce how consistently Claude follows them.
2. Split into .claude/rules/ as it grows
Once the root file is approaching that limit, move topic-specific guidance into .claude/rules/ - one file per topic, all .md files discovered recursively:
your-project/
├── CLAUDE.md
└── .claude/
└── rules/
├── code-style.md
├── testing.md
└── security.md
Rules without a paths field load unconditionally, at the same priority as the root CLAUDE.md - this is the default, and it’s how this blog’s own .claude/rules/ is set up (content rules, voice and style, post structure, SEO, all loaded every session regardless of which file is open).
3. Scope rules by path only where needed
Where a rule genuinely shouldn’t apply everywhere, add a paths field instead - Claude Code’s equivalent of Copilot’s applyTo frontmatter:
---
paths:
- "src/api/**/*.ts"
---
# API development rules
- All API endpoints must include input validation
- Use the standard error response format
Path-scoped rules trigger when Claude reads a matching file, not on every tool call - they don’t load at launch the way unconditional rules and the root CLAUDE.md do. The same applies to nested CLAUDE.md files in subdirectories: Claude discovers them, but only loads them when it actually reads a file in that subdirectory, not at session start.
.github/instructions/*.instructions.md model, the closest equivalent here is path-scoped rules under .claude/rules/ - not nested CLAUDE.md files. A nested CLAUDE.md is discovered lazily per subdirectory; it isn’t a guaranteed always-loaded file the way a path-scoped rule with a matching glob is.Rules also support symlinks, so a shared set can be linked into multiple projects:
ln -s ~/shared-claude-rules .claude/rules/shared
4. Use @ imports for anything pulled in by reference
CLAUDE.md files can pull in other files with @path/to/file syntax, expanded into context at launch alongside the file that references them:
See @README for project overview and @package.json for available npm commands.
# Additional instructions
- git workflow @docs/git-instructions.md
Imports can recursively import other files, up to four hops deep. Wrap a path in backticks (`@README`) to mention it without triggering an import. The first time a project’s imports are encountered, Claude shows an approval dialog listing the files - decline once and they stay disabled for that project.
One gotcha worth knowing up front: imports help with organisation, not context size. An imported file still loads in full at launch - splitting CLAUDE.md into imports doesn’t reduce what’s in context, only how it’s organised on disk.
5. Decide on AGENTS.md
Claude Code reads CLAUDE.md, not AGENTS.md, directly. If a repo already has an AGENTS.md for other coding agents, import it rather than duplicating content:
@AGENTS.md
## Claude Code
Use plan mode for changes under `src/billing/`.
A symlink works too if there’s no Claude-specific content to add on top:
ln -s AGENTS.md CLAUDE.md
On Windows, symlinks need Administrator privileges or Developer Mode - use the @AGENTS.md import instead. Running /init in a repo that already has an AGENTS.md reads it and folds the relevant parts into the generated CLAUDE.md automatically.
Resources
Notes
- This covers
CLAUDE.md, rules, and imports - the instructions you write. Skills (.claude/skills/) are a separate, related mechanism for packaging repeatable workflows that load on demand rather than every session, and auto memory is a third - notes Claude writes itself based on corrections and preferences. Both are worth their own post once there’s more to say. - Claude Code calls this system “memory,” not custom instructions - that term belongs to Copilot, and separately to claude.ai’s unrelated account-wide personalization feature (officially “Profile Preferences”).
- On the IDE side rather than the terminal, Configuring GitHub Copilot Custom Instructions covers the same ground for Copilot.