Most of my older projects have a CLAUDE.md file at the root. It accumulated content over months: project overview, commands, code style rules, infrastructure notes, credentials handling, git conventions. Some of those topics are genuinely project-specific. Others are personal preferences that apply to every project I work on.

When Claude Code added the .claude/rules/ convention (modular rule files auto-loaded by topic), the right move was to migrate. Generic rules (code style, git conventions, safety) belong in ~/.claude/rules/ so they apply everywhere. Project-specific rules (this repo’s build command, this framework’s patterns) belong in ./.claude/rules/. The CLAUDE.md shrinks to project overview only.

I did the migration manually on the first project. It took two hours and I missed one rule that should have been global. nf-claude-restructure is the skill I wrote so subsequent projects take ten minutes and the categorization is consistent.

The problem the skill solves

A legacy CLAUDE.md mixes three kinds of content:

  • Project context that should stay in CLAUDE.md: a one-paragraph overview of what the project does, where to find things, how to run it.
  • Project-specific rules that should move to ./.claude/rules/: framework conventions (React patterns, MUI sx prop usage), repo build commands, deploy specifics.
  • Generic rules that should move to ~/.claude/rules/: code style preferences (PascalCase for components), git conventions (commit format, branch naming), safety rules (never auto-push), .local/ folder usage.

Splitting these manually requires reading every line of CLAUDE.md and asking “would I want this rule on every project?” The skill encodes that decision matrix so the answer is consistent.

The skill is also documentation-aware: before doing anything, it fetches the latest Claude Code memory documentation to verify the conventions it is migrating to are still current. This matters because Claude Code conventions shift (the .claude/rules/ directory pattern itself is a relatively recent addition, and the auto-loading mechanism has evolved).

What it does

  • Fetches latest Claude Code documentation via WebFetch (memory docs, skills docs) and notes any new features or deprecations.
  • Asks the user which output mode they want: Local Only (personal, gitignored), Team Shared (commit CLAUDE.md and ./.claude/rules/), or Hybrid (per-category choice).
  • Discovers existing CLAUDE.md, CLAUDE.local.md, and ./.claude/rules/*.md.
  • Analyzes content against the latest docs: identifies outdated patterns, missing features, categorizes content into topics.
  • Auto-detects scope per rule using a decision matrix (generic vs project-specific based on tech stack references, path scoping, framework mentions).
  • Restructures content into ~/.claude/rules/ (global) and ./.claude/rules/ (project), branching on file existence so no existing rule is clobbered.
  • Validates the result: no duplicates, clear separation, proper gitignore setup for the chosen mode.

How to invoke

/nf-claude-restructure

No arguments. The skill is invocation-only (disable-model-invocation: true). You type the slash command when you want to migrate a project.

A walkthrough

You are on a project with a 300-line CLAUDE.md that has been growing for six months. You want to migrate it.

$ /nf-claude-restructure

Step 0: Fetching latest Claude Code documentation...
  - https://docs.anthropic.com/en/docs/claude-code/memory (200 OK)
  - https://docs.anthropic.com/en/docs/claude-code/skills (200 OK)

Discovery:
  Found:
    - CLAUDE.md (300 lines, last modified 2 weeks ago)
    - CLAUDE.local.md (45 lines, gitignored)
    - .claude/rules/ does not exist

Output mode:
  1. Local Only (Personal)        -- CLAUDE.local.md + .claude/rules/ (gitignored)
  2. Team Shared                  -- CLAUDE.md (overview) + .claude/rules/ (committed)
  3. Hybrid                       -- per-category choice
> 2 (Team Shared)

Analysis:
  Categorizing content from CLAUDE.md...

  | Category                  | Lines  | Auto-detected scope    |
  |---------------------------|--------|------------------------|
  | Project overview          | 12     | Stays in CLAUDE.md     |
  | Build/test/deploy commands| 34     | Project (./.claude)    |
  | Code style: generic       | 28     | Global (~/.claude)     |
  | Code style: React/MUI     | 41     | Project (./.claude)    |
  | Git conventions           | 22     | Global (~/.claude)     |
  | Safety rules              | 18     | Global (~/.claude)     |
  | Architecture notes        | 95     | Project (./.claude)    |
  | Credentials handling      | 14     | Mixed (asks per-line)  |
  | Infrastructure (Docker)   | 36     | Global (~/.claude)     |

  Outdated patterns found:
    - @import for .claude/rules/ entries (auto-loaded since CC 2.1.x, imports are redundant)

  Planned moves:
    ~/.claude/rules/code-style.md      <-- generic naming, no-emoji
    ~/.claude/rules/git.md             <-- commit format, branch naming
    ~/.claude/rules/safety.md          <-- never auto-push, sensitive data
    ~/.claude/rules/infrastructure.md  <-- Docker linux/amd64 default

    ./.claude/rules/commands.md        <-- npm scripts, build/test/deploy
    ./.claude/rules/code-style.md      <-- React + MUI patterns
    ./.claude/rules/architecture.md    <-- the long architecture section

  CLAUDE.md after restructure: ~30 lines (project overview only)

Apply changes?
  - Global rules will be MERGED into existing ~/.claude/rules/ files (Read + Edit, never Write).
  - Project rules will be CREATED (./.claude/rules/ is empty).
  - CLAUDE.md will be reduced to project overview.

> Yes

Writing...
  Wrote: ./.claude/rules/commands.md
  Wrote: ./.claude/rules/code-style.md
  Wrote: ./.claude/rules/architecture.md

  Existing: ~/.claude/rules/code-style.md (already has user content)
    -> Edit-merged: added "React/MUI" section under existing "Code Style" heading
  Existing: ~/.claude/rules/git.md
    -> No change: rules already cover commit format and branch naming
  Existing: ~/.claude/rules/safety.md
    -> Edit-merged: added 2 new entries under "Sensitive Data Storage"
  Wrote: ~/.claude/rules/infrastructure.md (did not exist)

  Updated: CLAUDE.md (300 lines -> 31 lines, project overview only)
  Untouched: CLAUDE.local.md (credentials section already correctly scoped)

Done.

Verify by opening a fresh Claude session on this project and asking "what rules are loaded?".

The “existing rules merged, not replaced” branch is what makes this safe to run on a machine that already has hand-curated ~/.claude/rules/. The skill never Writes over an existing rule file.

How it works under the hood

The skill is one SKILL.md plus a longer reference doc that ships in the folder. Five mechanisms:

Documentation fetch is mandatory. The first action is WebFetch against the official Claude Code docs URLs. The skill compares those docs against what the legacy CLAUDE.md is doing and notes any deprecated patterns (@import for .claude/rules/ entries is the most common one, since those files now auto-load). If the fetch fails, the skill falls back to a cached reference but warns explicitly that the cache may be stale.

Output mode asks first. Local Only, Team Shared, or Hybrid. This is the single biggest decision: who is going to read these rules. If you are the only developer on the project, Local Only keeps everything personal. If you are on a team, Team Shared writes CLAUDE.md and ./.claude/rules/ as committed files. Hybrid lets you mix.

Auto-detect scope via decision matrix. For every category extracted from the legacy CLAUDE.md, the skill applies a rubric:

Global (~/.claude/rules/) if:
  - No project-specific tech stack reference (no React, no MUI, no this-repo's-deploy)
  - Personal safety rule (never auto-push, ask before remote)
  - Git convention the user follows everywhere
  - Generic dev practice (no mock data, remove debug logs)

Project (./.claude/rules/) if:
  - Mentions specific framework or library by name
  - References specific directories in this project
  - Uses paths: frontmatter for file-scoped rules
  - Framework-specific conventions

The skill prints the matrix decision per category before applying, so you can override anything that auto-detection got wrong.

Branch on file existence (the most important mechanism). Every target path (~/.claude/rules/<name>.md, ./.claude/rules/<name>.md, CLAUDE.md, CLAUDE.local.md) is checked first:

test -f <path>
  not exists -> Write (new content)
  exists     -> Read + Edit (merge new content under existing headings)

This is the single biggest safety property. ~/.claude/rules/ is shared across all projects, often with rules tuned over months. Blindly Write-ing a rule file would wipe everything you have curated.

Validation pass at the end. Check for duplicate rules (same content in two files), clear separation (no project-specific text in ~/.claude/rules/), gitignore correctness (if Local Only mode picked, ensure ./.claude/rules/ is in .gitignore).

Gotchas

  • .claude/rules/ is auto-loaded, no imports needed. If the legacy CLAUDE.md had @.claude/rules/some-file.md imports, those are redundant in modern Claude Code and the skill removes them. Do not add them back; you will get duplicate loads.

  • Path-specific rules use frontmatter. A rule that only applies to .tsx files lives in ./.claude/rules/frontend.md with:

    ---
    paths: src/**/*.tsx
    ---

    The skill detects when a section is path-scoped and adds the frontmatter automatically.

  • The Hybrid mode is the most flexible but the slowest. Each category gets a separate question. Use Hybrid when the auto-detection is wrong on multiple categories, or when you need a non-default scope for one rule. For most projects, Team Shared or Local Only is fine and finishes in one pass.

  • CLAUDE.local.md rarely needs migration. It already lives in the right place (gitignored, personal, project-local). The skill only touches it if it contains generic rules that should be in ~/.claude/rules/, or if credentials live there mixed with non-credentials content.

  • Re-run after Claude Code upgrades. The skill checks the latest docs every time it runs. If Claude Code adds a new memory feature (a new directory pattern, a new auto-load behavior), re-running the skill identifies what is now outdated. The fetched docs are not cached aggressively for this reason.

Why I share this

The migration is a one-time task per project. The skill exists because doing it well requires a decision matrix that has fewer than ten rules but takes a beginner thirty minutes to internalize. Once the skill encodes the matrix, every subsequent project takes minutes instead.

For the underlying conventions, claude-code-claude-md-rules covers the CLAUDE.md vs .claude/rules/ split in detail, and the Claude Code Toolkit intro post explains why I publish my own rules as global vs project. For the related skill that writes new rules and skills correctly from the start, see claude-authoring.

If you have an old project with a 300-line CLAUDE.md and want to modernize, run /nf-claude-restructure. Pick Team Shared if you work with a team, Local Only if not. Review the proposed moves. Apply. The result should leave you with a 30-line CLAUDE.md (project overview only), a populated ./.claude/rules/, and a few new entries merged into your global ~/.claude/rules/.