My Advanced Claude Code Setup: 8 Layers, 60+ Skills, and Typed Memory
Five weeks ago I wrote a guide called "How to Give Claude Code Permanent Memory." Four layers. Twenty minutes. Templates you could copy-paste.
That guide got 569 views. People liked it. And it was fine. But it was also the starting point, not the destination.
Here's what actually happened after I followed my own advice for five weeks straight. The setup I use now barely resembles what I described in that article. It's not four layers anymore. It's at least eight. And the parts that matter most are the parts I couldn't have predicted on day one.
This is the advanced setup. Half tutorial, half lessons from five weeks of daily use.
One thing before we start: I use Claude Code, but everything here is markdown files. Cursor, Windsurf, and any agent that reads markdown can use this system. The hooks are Claude Code-specific, but the memory system, skills, trigger tables, and CLAUDE.md structure are tool-agnostic by design.
Default Claude Code vs 8-Layer Setup
Default Claude Code 8-Layer Setup Context loading Manual explanation every session Auto-loads global rules + project knowledge + memory Repeated mistakes Same errors across sessions Gotchas section prevents recurrence Workflow consistency Re-explain every time 60+ skills handle it Context window waste 30-40% spent on orientation Near-zero orientation overhead Multi-project switching Full re-briefing each time Trigger tables load context in one word Memory across sessions None (or unstructured auto-memory) Typed memory: user, feedback, project, reference
TL;DR: Split CLAUDE.md into global (behavior) and per-project (knowledge). Add a Gotchas section to every project. Build typed memory. Add a context-monitor hook. Turn repeated workflows into skills. Build trigger tables for natural-language shortcuts.
How to Split CLAUDE.md: Global vs Per-Project Configuration
The split between global and per-project CLAUDE.md files is the foundation of an advanced Claude Code setup. A global file at ~/.claude/CLAUDE.md controls agent behavior everywhere. A per-project file in each repo root provides project-specific knowledge. This separation scales cleanly across dozens of projects.
The first thing that broke was using a single CLAUDE.md for everything.
In Part 1, I said to put everything in CLAUDE.md: project context, workflows, decisions, constraints. That works for a single project. It falls apart when you're running 15+ projects with codebases and 4 more that are vault-only.
The problem: telling the agent how to behave is different from telling it what a project looks like. "Use kebab-case branches" is a behavior rule. "The database table is blog_posts, not posts" is project knowledge. Mixing them into one file creates a mess that scales poorly.
So I split CLAUDE.md into two layers.
Global CLAUDE.md lives at ~/.claude/CLAUDE.md and tells the agent how to behave everywhere. My preferences, my workflow rules, my git conventions, my deployment targets. ~200 lines. Loads every session regardless of which project I'm in.
Per-project CLAUDE.md lives in each project root. It tells the agent what it needs to know about THIS project. The architecture. The key files. The style patterns. And a Gotchas section where I log every mistake the agent makes so it doesn't repeat them.
The Gotchas section is the part I didn't expect to matter. Every time the agent does something wrong, I add a rule. "Next.js 16 params are Promises, always await them." "The table is blog_posts not posts." "FFmpeg filter escaping needs double backslashes." After five weeks, I have 100+ gotchas across all projects. The agent reads them at the start of every session.
The difference was immediate. Not because the agent got smarter. Because I stopped letting it make the same mistake twice.
A note on .claude/rules/
Since Claude Code v2.0.64, there's also a .claude/rules/ directory for splitting instructions by concern -- testing.md, security.md, style.md, etc. This is complementary to the two-CLAUDE.md approach, not a replacement. The rules directory splits by topic within a project. My two-file split is between global behavior and project knowledge -- a different axis entirely. I use both: .claude/rules/ for granular topic-based rules within larger projects, and the global/per-project CLAUDE.md split for the high-level separation.
How to set it up:
Create a CLAUDE.md in your project root:
# [Project Name] — Agent Guide
## Architecture
[How the system works. Key files. Data flow.]
## Patterns
[Code patterns used in this project. Naming conventions.]
## Gotchas
- [Every mistake the agent made, turned into a rule]
- [Be specific: "Don't use X, use Y because Z"]
- [Include the WHY so the agent knows when the rule applies]
## Current Status
[What's done, what's in progress, what's blocked]
Corrections become rules. Rules prevent repeated mistakes. After a month, the agent barely makes project-specific errors anymore because every error became a line in CLAUDE.md.
Typed Memory System: User, Feedback, Project, and Reference Notes
Claude Code's typed memory system separates context into four categories -- user, feedback, project, and reference -- so the agent loads only what's relevant to each task. This is more structured than dumping everything into a single file and more intentional than auto-generated notes.
Part 1 used the Obsidian vault as a flat store. "Put your project notes here, the agent reads them." That's version one.
Version two has types.
I realized AI agents need different kinds of memory. Knowing that I'm a technical orchestrator (not a traditional developer) is different from knowing that I hate trailing summaries at the end of responses. And both are different from knowing that the merge freeze starts on Thursday.
So I built a typed memory system:
~/.claude/projects/my-project/memory/
├── MEMORY.md ← Index (like a table of contents)
├── user_role.md ← Who I am, what I know
├── feedback_testing.md ← "Don't mock the database"
├── project_freeze.md ← "Merge freeze starts March 5"
└── reference_linear.md ← "Bugs tracked in Linear project INGEST"
Four types:
User memories. My role, skills, preferences. The agent tailors explanations differently for a senior engineer vs. a student. I'm somewhere in between, and the agent knows that now.
Feedback memories. Corrections I've given. "Stop summarizing at the end of every response." "Don't create separate lessons.md files, everything goes in CLAUDE.md." These prevent me from repeating the same correction across sessions.
Project memories. Who's doing what, by when, and why. Business context that isn't in the code or git history.
Reference memories. Where to find things in external systems. "Pipeline bugs are in Linear project INGEST." "The oncall dashboard is at grafana.internal/d/api-latency."
MEMORY.md is just an index with links. Each memory file has frontmatter:
---
name: user-role
description: Misha is a technical orchestrator, not a traditional dev
type: user
---
Background in product management. Proficient in Python. Some frontend.
Directs AI to write code. Expertise is in orchestration and knowing
which tool solves which problem.
The description field matters. The agent uses it to decide whether a memory is relevant to the current task. A good description means the agent loads the right context without loading everything.
What about Claude Code's built-in auto-memory?
Claude Code now has a built-in auto-memory feature (toggle it via /memory). It works -- the agent saves notes automatically and loads them next session. But auto-memory is unstructured. It's a running list of observations without categories or priority.
My typed system is still valuable because it separates concerns. User preferences don't mix with project deadlines. Feedback corrections don't get buried under reference links. The description field on each memory file lets the agent quickly decide what's relevant. I use both: auto-memory catches things I forget to save manually, and the typed system provides the structured foundation. They're complementary.
I won't lie. Setting this up took more than 20 minutes. But the feedback memories alone saved me probably an hour per week of repeating corrections.
Claude Code Hooks: Context Monitor, Gotchas Auto-Capture, and More
A Claude Code hook is a script that runs automatically at specific points in a session -- after tool use, on session start, or on subagent spawn. The context-monitor hook is the most impactful: it warns the agent when the context window is running low, preventing lost work.
This one surprised me the most.
Every AI coding agent has a context window. It's large, but it's finite. And the agent itself has no idea how much of it is used. It will happily keep working until it hits the wall, then lose context of what it was doing.
The fix is a hook. Specifically, a PostToolUse hook that checks context usage after every tool call and injects a warning when it's running low.
~/.claude/hooks/context-monitor.js
Two thresholds:
- Warning at 35% remaining: "Wrap up your current task."
- Critical at 25% remaining: "Stop. Save state. Summarize progress."
The hook reads metrics from a bridge file, checks the numbers, and adds a message to the conversation. The agent sees the warning and adjusts. Nothing fancy. It just gives the agent information it didn't have before.
Before this hook, I'd lose work regularly. The agent would be in the middle of a complex refactor, run out of context, and the session would compress away the details it needed. Now it wraps up cleanly because it knows the wall is coming.
How to set it up:
In your ~/.claude/settings.json, add a hook:
{
"hooks": {
"PostToolUse": [
{
"type": "command",
"command": "node ~/.claude/hooks/context-monitor.js"
}
]
}
}
The hook script reads stdin (which includes session metrics), checks remaining context percentage, and outputs a warning message if needed. The implementation depends on your setup, but the principle is simple: give the agent visibility into its own constraints.
I also have a SessionStart hook that runs on every new conversation. It loads output style preferences and checks for tool updates. Three hooks total. Each one solves a specific problem I hit repeatedly.
How to Build 60+ Claude Code Skills (And Why It's Not Overkill)
A Claude Code skill is a markdown file that encodes a repeatable workflow -- trigger, steps, and quality checks. Building 60+ skills sounds excessive, but each one takes 5-10 minutes to create and eliminates repeated explanations forever.
Part 1 showed one example skill. "Content planning." I called skills "optional but powerful."
Five weeks later I have 60+ of them. That sounds insane. It's not.
Here's what happened. Every time I found myself explaining a workflow to the agent for the second time, I turned it into a skill. Write a blog post? Skill. Audit SEO? Skill. Review a PR? Skill. Log a training session to my database? Skill.
Each skill is a markdown file with a clear trigger and a step-by-step process. When I type /blog-write, the agent knows the exact structure, formatting rules, SEO requirements, and quality checks. I don't explain it. I don't remember it. The skill handles it.
The ones that surprised me:
human-writing-editor runs as a mandatory final pass on everything I publish. It catches AI-sounding phrases, removes em dashes, flags performative confidence. I can't put a number on how much it improved my content, but I stopped getting "this reads like ChatGPT" comments.
obsidian-cleanup is a vault health check. Validates frontmatter, fixes broken links, audits naming conventions. I run it once a week. It finds things I'd never catch manually.
daily-digest scans all my coding sessions from the day and extracts interesting insights. Turns my work sessions into content ideas -- which is how I came up with this post about building a personal dashboard with 7 APIs.
The 60+ number sounds like a lot, but each skill took 5-10 minutes to write and saves that time back every single use. I spend my time building, not explaining.
The structure that works:
---
name: my-skill
description: When to use this. Be specific so the agent invokes it correctly.
---
# Skill Name
## Before Starting
[What context to gather. What to ask the user.]
## Process
[Numbered steps. Be explicit. The agent follows these literally.]
## Quality Checks
[What "done" looks like. Validation steps.]
Be specific in the description. The agent uses it to decide whether to invoke the skill. "When the user wants to write a blog post" works. "For content" doesn't.
Trigger Tables: Natural Language Shortcuts for Claude Code
A trigger table maps natural-language phrases to specific agent actions in your global CLAUDE.md. Say "training" and the agent loads your fitness data. Say "deploy" and it reads your deployment matrix. No prompting gymnastics required.
This is the simplest upgrade and maybe the most useful.
In my global CLAUDE.md, I have a table:
| When I Say | What the Agent Does |
|---|---|
| "training" | Read Body/CLAUDE.md, query training.db |
| "twitter" | Read Brand/Twitter/project.md |
| "packd" | Read Work/Packd/CLAUDE.md |
| "deploy" | Read Work/Deployment Matrix.md |
| "tasks" | Read Task Board, show status |
13 triggers. Each one maps a word I naturally say to a location the agent should check.
Before this, I'd say "let's work on Packd" and then spend two minutes telling the agent where the project lives, what the tech stack is, and what I was working on last time. Now I say "packd" and it already knows. It reads the project CLAUDE.md, loads the context, and asks what I want to do next.
Consistent phrases beat clever prompting. I trained myself to say the same word every time. "Training" always means Body/. "Deploy" always means the deployment matrix. The agent doesn't have to guess.
The Gotchas System: How Claude Code Stops Repeating Mistakes
The Gotchas section in each per-project CLAUDE.md is a self-improving error log. Every time the agent makes a mistake, the correction becomes a permanent rule. After 100+ gotchas across 15 projects, Claude's project-specific error rate dropped to near zero.
Two things actually improved, both measurable.
Token efficiency. Before the advanced setup, I'd burn 30-40% of my context window just getting the agent oriented. Explaining the project, repeating preferences, re-stating constraints. Now that happens automatically. The global CLAUDE.md loads, the project CLAUDE.md loads, memory loads, triggers fire. I start working within the first message.
Output quality. The Gotchas section was the biggest lever. When the agent already knows "don't use that API, it changed in v3" or "the table name is blog_posts not posts," it doesn't make those mistakes. I spend less time correcting and more time building.
I can't give you exact percentages. I didn't measure context usage before and after. But the difference is obvious enough that going back to a basic setup would feel like starting over.
The setup I'd recommend
If you already followed Part 1, here's what to add:
-
Split CLAUDE.md into two layers. Global CLAUDE.md at
~/.claude/CLAUDE.mdfor behavior. Per-project CLAUDE.md in each project root for knowledge. -
Add a Gotchas section to every project CLAUDE.md. Every time the agent makes a mistake, turn it into a rule. This is the highest-ROI habit.
-
Set up typed memory. Start with feedback memories (corrections you repeat). Add user and project memories as they come up naturally.
-
Add one hook. The context monitor is the most useful. Start there.
-
Turn repeated workflows into skills. Don't create 60 on day one. Just notice when you're explaining the same thing twice and make it a skill.
-
Build trigger tables. Map the words you already say to the locations the agent should check.
None of this takes 20 minutes. It takes weeks of daily use. But each piece solves a real problem you'll hit if you use AI coding agents seriously. The basic setup gets you started. This is what makes it stick.
Frequently Asked Questions
What is the difference between a global CLAUDE.md and a per-project CLAUDE.md?
A global CLAUDE.md lives at ~/.claude/CLAUDE.md and contains behavior rules that apply to every project -- git conventions, coding preferences, and workflow rules. A per-project CLAUDE.md lives in each project root and contains project-specific knowledge: architecture, key files, patterns, and a Gotchas section. The global file tells Claude how to behave; the project file tells it what it needs to know.
How do you prevent Claude Code from making the same mistake twice?
Add a "Gotchas" section to your per-project CLAUDE.md. Every time Claude makes a mistake, turn the correction into a rule: "Don't use X, use Y because Z." Claude reads this section at the start of every session. After five weeks, I accumulated 100+ gotchas across 15 projects, and Claude's error rate on project-specific issues dropped dramatically.
How many Claude Code skills do you need?
Start with zero. Add a skill only when you find yourself explaining the same workflow for the second time. After five weeks of daily use, I built 60+ skills -- but each one took only 5-10 minutes to create and saves that time back on every use. Common high-value skills include code review, blog writing, SEO auditing, and database logging.
How do you monitor Claude Code's context window usage?
Use a PostToolUse hook that checks context usage after every tool call. Set two thresholds: a warning at 35% remaining context and a critical alert at 25%. The hook injects a message into the conversation telling Claude to wrap up or save state. This prevents losing work when context runs out mid-task.
Does this Claude Code setup work with Cursor and other AI coding tools?
Yes. The entire system is tool-agnostic. CLAUDE.md is just a markdown file -- Cursor, Windsurf, and any agent that reads markdown can use it. The hooks are Claude Code-specific, but the memory system, skills structure, and trigger tables are portable across tools.
How long does it take to set up an advanced Claude Code configuration?
The basic split (global + per-project CLAUDE.md) takes 30 minutes. Adding typed memory takes another hour. Building skills accumulates over weeks -- each one takes 5-10 minutes, and you add them as needs arise. The full 8-layer system took about 5 weeks of daily use to reach its current state. Start with layers 1-3 and build from there.
What is a trigger table in Claude Code?
A trigger table is a mapping in your global CLAUDE.md that connects natural-language phrases to specific actions. For example, when you say "training", Claude automatically loads your Body/CLAUDE.md and queries your training database. When you say "deploy", it reads your deployment matrix. This eliminates the need to explain project locations at the start of every session.