Claude Code, Dissected
I want you to imagine you are opening a project folder and you see a hidden folder called .claude. Most people ignore it. They think it is just some internal thing. But I am here to tell you that this folder is the command center for your AI assistant. It holds the keys to how Claude behaves, remembers, and works inside your codebase. Once you understand its anatomy, you can make Claude work exactly the way you want without repeating yourself.
Let me walk you through the five main pillars that make this folder powerful. These are persistent memory, custom slash commands, reusable behaviours, sub agent definitions, and hard constraints. I will show you what each part does, how to set it up, and give you real examples you can start using today.
To make this concrete, here is a bird’s eye view of what we are building inside your project:
your-project/
├── CLAUDE.md # the main instruction manual
├── CLAUDE.local.md # your personal notes (not shared)
│
└── .claude/
├── settings.json # the rulebook of what is allowed
├── settings.local.json # your personal rule overrides
│
├── commands/ # your custom slash commands
│ ├── review.md
│ └── fix-issue.md
│
├── rules/ # modular instructions
│ ├── code-style.md
│ └── testing.md
│
├── skills/ # reusable workflows that run on their own
│ └── security-review/
│ └── SKILL.md
│
└── agents/ # specialised sub personas
├── code-reviewer.md
└── security-auditor.md
Two Folders, Not One
Before we dive into the details, there is something important you need to know. There are actually two .claude directories, not just the one inside your project.
The first is the one you see above; the project level folder. You commit this one to git. Everyone on your team gets the same rules, the same custom commands, the same permission policies. It lives right inside your repository.
The second lives in your home directory at ~/.claude/. This folder is personal to you and stays on your machine. You never commit it. It holds your own preferences, your personal slash commands, and even Claude’s memory of what it has learned across different projects.
Why have two? Because some things belong to the team; like “always use the shared logger” and some things belong to you, like “always explain your reasoning step by step” or “prefer functional patterns”. The project folder makes sure everyone works consistently. The global folder makes sure Claude works the way you like, no matter which repository you open.
Now let’s look at each piece of the project level folder in detail, and I will point out when you can also use the global version.
Persistent Memory: How Claude Remembers Who You Are
The first thing you need is a way to tell Claude the permanent facts about your project. What commands do you use to run tests? What folder holds your API routes? What are the unwritten rules that everyone on the team follows? That is what persistent memory is for.
The most important file here is CLAUDE.md. I like to think of it as Claude’s onboarding manual. Every time you start a new session, Claude reads this file and loads it into its brain. It stays there for the whole conversation.
Here is a real example of what I put in my CLAUDE.md for a typical Node.js API:
# Project: Acme API
## Commands
npm run dev # start the dev server
npm run test # run tests using Jest
npm run lint # check code style with ESLint
npm run build # create a production build
## Architecture
We are using Express with Node 20.
Database is PostgreSQL accessed through Prisma ORM.
All request handlers go into src/handlers/.
Shared types live in src/types/.
## Conventions
Every handler must validate inputs with Zod.
The return shape is always { data, error }.
Never expose raw stack traces to the client.
Use the logger module instead of console.log.
## Watch out for
Tests run against a real local database, not mocks.
You must run `npm run db:test:reset` before testing.
TypeScript strict mode is on; unused variables are errors.
That is about twenty lines. It gives Claude everything it needs to work without me having to explain the same things over and over.
But what if you have a personal preference that the team does not share? Maybe you want Claude to always open files using a specific pattern or to explain things in more detail. That is where CLAUDE.local.md comes in. You put this file in your project root and it gets loaded alongside the main CLAUDE.md. It is automatically ignored by git, so your personal tweaks never end up in the shared repository.
Now, as your project grows, you might find that CLAUDE.md becomes too long. That is when you use the rules/ folder. Instead of one giant file, you split instructions into smaller markdown files inside .claude/rules/. Each file can focus on one area.
.claude/rules/
├── code-style.md
├── testing.md
├── api-conventions.md
└── security.md
The real magic is that you can make rules apply only when Claude is working with certain files. You add a frontmatter block at the top with a paths field. For example, I have an api-conventions.md file that only applies to my API folder:
---
paths:
- "src/api/**/*.ts"
- "src/handlers/**/*.ts"
---
# API Design Rules
All handlers return { data, error } shape.
Use zod for request body validation.
Never expose internal error details to clients.
Now Claude will only load these instructions when it is editing inside src/api/ or src/handlers/. It keeps the context clean and relevant.
There is also a global memory that lives outside your project. In your home directory, you have a folder at ~/.claude/ . Inside it, there is a CLAUDE.md file that loads into every session, across all your projects. I use this to store my personal coding principles, like “always use functional patterns over classes” or “prefer early returns to nested conditionals”. This memory follows me wherever I go.
Custom Slash Commands: Your Shortcuts to Common Tasks
Now let’s talk about custom slash commands. These are like your own personal macros. Instead of typing out a long request every time, you create a short command that does the heavy lifting for you.
All you have to do is create a markdown file inside .claude/commands/. The filename becomes the command name. For example, if I create a file called review.md, I can later type /project:review and Claude will run that command.
Here is a simple but powerful command I use for code reviews. I create .claude/commands/review.md with the following content:
---
description: Review the current branch diff for issues before merging
---
## Changes to Review
!`git diff --name-only main...HEAD`
## Detailed Diff
!`git diff main...HEAD`
Review the above changes for:
1. Code quality issues
2. Security vulnerabilities
3. Missing test coverage
4. Performance concerns
Give specific, actionable feedback per file.
The exclamation mark followed by backticks is a special syntax that tells Claude to run a shell command and embed the output right into the prompt. So when I run /project:review, Claude sees the actual diff of my branch compared to main, and then it does the review. I do not have to copy paste anything.
You can also pass arguments to your commands. Use $ARGUMENTS in the file. For example, I have a command to investigate GitHub issues:
---
description: Investigate and fix a GitHub issue
argument-hint: [issue-number]
---
Look at issue #$ARGUMENTS in this repo.
!`gh issue view $ARGUMENTS`
Understand the bug, trace it to the root cause, fix it, and write a test that would have caught it.
Now I can type /project:fix-issue 234 and Claude fetches the issue details and starts working on it. It feels like having a dedicated assistant.
If you have commands that you want to use in every project, put them in ~/.claude/commands/. They will show up as /user:command-name and are always available.
Reusable Behaviours: Skills That Act on Their Own
The next layer is about behaviours that Claude can invoke by itself, without you typing a slash command. These are called skills. They live in the skills/ folder.
Recommended by LinkedIn
A skill is like a packaged workflow. Each skill has its own subdirectory with a SKILL.md file. The file uses YAML frontmatter to tell Claude when it should use this skill.
Let me show you a skill for security reviews. I create a folder .claude/skills/security-review/ and inside it a file SKILL.md:
---
name: security-review
description: Comprehensive security audit. Use when reviewing code for vulnerabilities, before deployments, or when the user mentions security.
allowed-tools: Read, Grep, Glob
---
Analyze the codebase for security vulnerabilities:
1. SQL injection and XSS risks
2. Exposed credentials or secrets
3. Insecure configurations
4. Authentication and authorization gaps
Report findings with severity ratings and specific remediation steps.
Reference @DETAILED_GUIDE.md for our security standards.
The description field is key. When I say something like “can you review this pull request for security issues”, Claude reads that description, sees it matches, and activates the skill automatically. I do not have to remember a special command.
You can also reference supporting files using the @ symbol. In this example, I reference DETAILED_GUIDE.md, which can be placed right next to SKILL.md. That guide might contain a long checklist or company standards. Skills let you bundle all that context together.
Commands are single files, but skills are packages. That makes them perfect for complex workflows that need extra documentation, templates, or scripts.
Just like with commands, you can put personal skills in ~/.claude/skills/ and they will be available across all your projects.
Sub Agent Definitions: Specialised Personas for Complex Tasks
Sometimes a task is so large or specialised that you want to give it a dedicated sub agent. This is like spinning off a mini assistant with its own system prompt, tool access, and even its own model. These sub agents live in the agents/ folder.
Each agent is a markdown file. I will show you a code reviewer agent. I create .claude/agents/code-reviewer.md:
---
name: code-reviewer
description: Expert code reviewer. Use PROACTIVELY when reviewing PRs, checking for bugs, or validating implementations before merging.
model: sonnet
tools: Read, Grep, Glob
---
You are a senior code reviewer with a focus on correctness and maintainability.
When reviewing code:
- Flag bugs, not just style issues
- Suggest specific fixes, not vague improvements
- Check for edge cases and error handling gaps
- Note performance concerns only when they matter at scale
What happens when Claude decides to use this agent? It spawns a separate session with its own context window. That agent has the system prompt I gave it, and it is restricted to the tools I listed. In this case, it can only read files, search with grep, and use glob patterns. It cannot write code. That is intentional and safe.
The agent does its work, compresses the findings, and reports back to the main session. This keeps the main conversation clean and focused. The main session does not get flooded with thousands of tokens of intermediate exploration.
I also set the model field to sonnet. For simpler, read only tasks, I can use a cheaper model to save on costs. For the main coding work I might use opus. This fine grained control is surprisingly useful.
You can also create agents for security audits, documentation generation, or even as a “stubborn skeptic” that tries to break your designs. The possibilities are endless.
Hard Constraints: The Rules Claude Cannot Break
The final piece is about safety and boundaries. You need a way to say “this is not allowed, no matter what”. That is what the settings.json file inside .claude/ is for. It defines hard constraints.
Here is an example of a settings.json that I use for most projects:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git status)",
"Bash(git diff *)",
"Read",
"Write",
"Edit"
],
"deny": [
"Bash(rm -rf *)",
"Bash(curl *)",
"Read(./.env)",
"Read(./.env.*)"
]
}
}
The allow list tells Claude which commands it can run without asking me for confirmation. For example, I let it run any npm script and any read only git command. It can also read, write, and edit files freely.
The deny list is the hard stop. I block destructive shell commands like rm -rf. I block direct network calls with curl. I also block access to my .env files because those contain secrets.
If a command is not in either list, Claude will ask me before proceeding. That middle ground gives me a safety net without having to anticipate every possible command.
Just like with the other parts, you can have a personal override file called settings.local.json in the .claude/ folder. It is automatically ignored by git, so you can add personal allowances or denials without affecting the team.
Bringing It All Together: A Practical First Setup
If you are starting from scratch, I recommend this simple progression.
First, run /init inside Claude Code. It will look at your project and generate a starter CLAUDE.md. Then edit that file down to just the essentials: your build commands, your architecture, your key conventions. Keep it under 200 lines.
Second, add a .claude/settings.json with a minimal allow list. At a minimum, allow your test and build commands, and deny reads of your .env files.
Third, create one or two custom commands for the tasks you do most often. For me, that is a code review command and an issue fix command.
Fourth, as your CLAUDE.md starts to feel crowded, start splitting rules into .claude/rules/ files. Use path scoping to keep them focused.
Finally, add a personal ~/.claude/CLAUDE.md with your own preferences. This will apply to all projects and it is a great place to store your own coding principles.
You do not need to use skills and agents on day one. They are there for when you have recurring complex workflows that you want to package up and reuse.
The Big Picture
What we have covered here is the anatomy of the .claude folder. It is really a protocol for telling Claude who you are, what your project does, and how you want things done.
Persistent memory through CLAUDE.md and rules ensures Claude always has the right context. Custom slash commands give you quick shortcuts for repetitive tasks. Reusable behaviours through skills let Claude help you proactively. Sub agent definitions let you delegate specialised work to focused assistants. Hard constraints through settings.json keep everything safe and predictable.
When you set these up properly, you stop spending time correcting Claude and start spending time building. It is one of those investments that pays off every single day.
I encourage you to open your .claude folder right now, look inside, and start shaping it. It is your control center. Own it.
Revocent, Inc.•4K followers
2dNice work Rohan! Definitely learned a lot from this! Oh, BTW are you a real person or AI? :)
StableIDs•4K followers
3dIf possible, one of the things that I would build, would be a business development info scraping agent, using a skill that would point it towards LinkedIn profiles, and anything on those profiles that could lead to "social selling." Went to a College where the mascot is a Wildcat? That'd be used in a custom subject line when prospecting so the lead/recipient knows the email is meant for them. Have a personal website that details your interests? Enable the skill to mirror those interests, and propose ideas on how to write a genuine intro/subject line, without coming off as inauthentic. This was a manual process for me during my early BDR days, and it was another way to connect with someone while interjecting some personal connections into the conversation. Example: The former Chief Innovation Officer for the City of Miami a decade ago, was in a band that had music on SoundCloud. One of their influences listed was a producer I opened for (played a DJ set right before), so I mentioned his band and the producer in the subject line. We still chat about music, and had productive business talks too. Same with the former CIO of Adams County, CO. His personal website had poetry on it, so I wrote him a poem, with a CTA at the end.
1Kosmos•8K followers
3dWhat a great overview, Rohan. I've been so impressed with Claude Code and I'm not a coder but it's really helped me with a ton of projects, especially configuring OpenClaw.
ThriveConsultingHQ•1K followers
5dThe .claude folder is where the real separation starts. Most people using Claude Code have never touched it. They're running the same generic context every session, wondering why the output keeps drifting. The ones who've built proper CLAUDE.md files, custom slash commands, and hard constraints - they're not using the same tool. They've built a different tool on top of it. I've been inside Claude Code for months on real builds. M's in tokens spent. The difference between a clean session with proper memory scaffolding and a blank-context session isn't marginal. It's the difference between a system that compounds and one that hallucinates in circles. But here's what the .claude folder doesn't fix: the flattery. You can have the cleanest memory architecture, the tightest slash commands, every constraint dialed in - and Claude will still tell you "great instinct here." It will still call your Dockerfile elegant before the pod crashes. The workflow gets sharper. The sycophancy doesn't. That's what I wrote about - why the flattery never turns off, and why power users end up the most delusional. Worth reading: https://www.linkedin.com/pulse/how-did-he-create-facebook-without-using-claude-alaba-miracle-sdsee
Eduonix Learning Solutions…•26 followers
5d100% agree with this. I used to think I was “using AI” properly until I realized I was barely scratching the surface. The difference is honestly in how you use it — workflows vs random prompts. Came across something recently that explains this really well with real-world use cases: https://bit.ly/4uRWJp6