# Onboarding Claude Code Harness: The Hard Way

I've been running Claude Code daily for exploratory and experimental work driver for a little while now, and the single biggest realization I've had is this:

> Claude model is not the product. The harness is.

The model you get is the same as everyone else. What *possibly* makes it feel like a \_seasoned\_ senior colleague is the machinery config. around the model: **what** loads into context - always or as-required, **when** it loads, and **what gets enforced rather than merely suggested.**

The best mental model I've found is **onboarding**. You can't drop a new hire into a codebase with zero docs. and expect them to be productive from day one.

> This post is my WIP notes on how to onboard it properly, written partly so I could come back and refresh my own memory, and *possibly* for other enggineers who are new and are looking for technical hygiene before they start.

![](https://cdn.hashnode.com/uploads/covers/6a25ff63980616b1c020fc7a/a86115b1-8cc8-48ed-9ae2-6bb413b72810.png align="center")

### CLAUDE.md is NOT the system prompt

A lot of content out there incorrectly (personally) describes memory files as "the system prompt" for your agent. According to the [docs](https://code.claude.com/docs/en/glossary#claude-md), CLAUDE.md content is **delivered as a user message *after* the system prompt, not as part of the system prompt itself**. This matters -

*   it explains why compliance is probabilistic. Claude reads your CLAUDE.md and tries to follow it, but there is **no guarantee of strict adherence**, especially for vague or contradictory instructions. Claude's own docs are blunt about this. For example -
    
*   Second, it tells you where the real system prompt hook is. If you genuinely need instructions at the system prompt level, pass them at startup.
    

![](https://cdn.hashnode.com/uploads/covers/6a25ff63980616b1c020fc7a/a791a210-7f61-40b4-aaa8-6b4bee807a41.png align="center")

So CLAUDE.md is essentially context that shapes behavior.

## Important Concept: memory hierarchy

> I've done my best - as of June 2026 - to arrange up-to-date info., but it may get out-dated by the time you're reading this blog.

Claude Code [reads](https://code.claude.com/docs/en/memory#choose-where-to-put-claude-md-files) memory files from several locations, each with a different scope:

| Scope | Location | Purpose | Use case examples | Shared with |
| --- | --- | --- | --- | --- |
| **Managed policy** | • macOS: `/Library/Application Support/ClaudeCode/`[`CLAUDE.md`](http://CLAUDE.md),• Linux and WSL: `/etc/claude-code/`[`CLAUDE.md`](http://CLAUDE.md) |  |  |  |
| • Windows: `C:\Program Files\ClaudeCode\`[`CLAUDE.md`](http://CLAUDE.md) | Organization-wide instructions managed by IT/DevOps | Company coding standards, security policies, compliance requirements | All users in organization |  |
| **User instructions** | `~/.claude/`[`CLAUDE.md`](http://CLAUDE.md) | Personal preferences for all projects | Code styling preferences, personal tooling shortcuts | Just you (all projects) |
| **Project instructions** | `./`[`CLAUDE.md`](http://CLAUDE.md) or `./.claude/`[`CLAUDE.md`](http://CLAUDE.md) | Team-shared instructions for the project | Project architecture, coding standards, common workflows | Team members via source control |
| **Local instructions** | `./`[`CLAUDE.local.md`](http://CLAUDE.local.md) | Personal project-specific preferences; add to `.gitignore` | Your sandbox URLs, preferred test data | Just you (current project) |

The two-tier "global plus project" advice I've seen in YT videos is a tad-bit over-simplification.

*   Your user-level file at `~/.claude/CLAUDE.md` is where personal preferences live:
    
    *   formatting quirks you hate,
        
    *   tooling shortcuts,
        
    *   style opinions that follow you across every repo.
        
*   The project file is where the team's collective knowledge lives: build commands, architecture, terminology, testing conventions.
    

The official [guidance](https://code.claude.com/docs/en/memory#claude-md-vs-auto-memory) gives you the actual target size for [CLAUDE.md](http://CLAUDE.md): keep under 200 lines. Longer files consume more context on every single request and, more importantly, potentially reduce adherence.

> A bloated memory file doesn't just cost tokens; it makes the model worse at following rules - instructions may get lost in the noise.

### How Context loading works?

Claude Code discovers memory files by walking *up* the directory tree from your working directory to the fs root, collecting every `CLAUDE.md` and `CLAUDE.local.md` along the way, and that gets loaded in full at launch.

What I really found interesting was to learn that the files don't override each other, instead **they are concatenated into context, ordered from the root down to your working directory**.

> so the instructions "closest" to you are the last thing the model reads.

Within your project dir., CLAUDE.local.md is appended after CLAUDE.md. This also suggest *lower-level* instructions like [`CLAUDE.local.md`](http://CLAUDE.local.md) might get dropped first it the context fills up.

Files in subdirs. *below* the working directory behave differently: **they load lazily**, only when Claude actually reads a file in that subdirectory consuming 0 tokens before the agent walks into it.

### Path-scoped rules: the middle tier

Between "always loaded" CLAUDE.md and "loaded on demand" skills sits `.claude/rules/`, and I personally didn't find a lot of content on them as of June 2026. For example -

```markdown
---
paths:
  - "src/api/**/*.{ts,tsx}"
---

# API rules
- All endpoints must include input validation
- Use the standard error response format
```

A rule with `paths` loads only when Claude reads files matching the glob.

So the way I've understood is that a fact that is needed every session goes in CLAUDE.md. Where as a convention tied to a file type or directory goes in a path-scoped rule. A multi-step procedure goes in a skill.

### The collective intelligence loop

Treat the project CLAUDE.md as the teams' accumulated corrections.

> Add an entry when Claude makes the same mistake a second time

For example, when code review catches something it should have known about this codebase, or when you notice yourself typing the same clarification you typed last session.

> Every correction you document is a mistake the whole team stops paying for.

Newer Claude Code versions also close this loop automatically. [Auto memory](https://code.claude.com/docs/en/memory#auto-memory) lets Claude write notes to itself in `~/.claude/projects/<project>/memory/`, keyed to the git repo so all worktrees share it.

### What survives compaction

Long sessions eventually hit auto-compaction so knowing what survives is worth a lot of debugging time: your project-root CLAUDE.md is re-read from disk and re-injected after `/compact`. Nested CLAUDE.md files are not; they reload only the next time Claude touches a file in their subdir.

> Instructions given purely in conversation are the most fragile thing you have. If something mattered enough to say twice, it belongs in a file.

## Skills and progressive disclosure

Everything in CLAUDE.md is a tax on every request, whether or not it's relevant to the task. For example, an e2e testing protocol is 100 lines that matter in maybe 1 session out 20. Skills solve this with progressive disclosure.

A skill is a directory containing a `SKILL.md` with YAML frontmatter and markdown instructions:

```yaml
---
description: Run the full e2e suite against a staging deploy. Use when the
  user asks to verify a release candidate or run end-to-end tests.
---

1. Build with `pnpm build:staging`
2. Deploy the preview with `./scripts/preview.sh`
3. Run `pnpm e2e --env staging`, retry flaky tags once
4. Post the summary; never mark green with skipped suites
```

**At session start, only the** `description` **of each skill enters context so Claude knows what's available**.. The full body loads only if/when required - Claude matched your request to the description or you invoked it directly as `/skill-name`.

Anthropic's guideline is to keep SKILL.md under 500 lines and push heavy reference material into supporting files in the same directory, which Claude reads on demand with its normal file tools.

Skills live in `~/.claude/skills/<name>/SKILL.md` for personal ones and `.claude/skills/<name>/SKILL.md` for project ones, with plugin and enterprise tiers above that.

### The frontmatter is where the power is

A handful of fields turn skills from "saved prompts" into real workflow machinery.

*   `disable-model-invocation: true` makes a skill user-only. Claude can't trigger it, and its description doesn't even load into context, so it costs zero tokens until you type the slash command.
    
*   `allowed-tools` pre-approves specific tools while the skill is active which kills the permission-prompt friction for well-scoped workflows. `context: fork` runs the skill in a forked subagent context.
    

### Skill lifecycle under compaction

Once invoked, a skill's content enters the conversation as a message and stays there, so mid-session edits to an already-loaded skill don't take effect until you re-invoke it. Under auto-compaction, Claude Code re-attaches the most recent invocation of each skill after the summary.

## Context economics, briefly

It helps to see the whole extension surface priced in context terms, because the features form a spectrum from always-on to zero-cost:

| Feature | Loads | Steady-state cost |
| --- | --- | --- |
| CLAUDE.md | Session start, full content | Every request |
| Rules (path-scoped) | When matching files are read | Only in relevant sessions |
| Skills | Descriptions at start, body on use | Low until invoked |
| MCP servers | Tool names at start, schemas deferred | Low until a tool is used |
| Subagents | Spawned with fresh context | Isolated from your window |
| Hooks | Run externally on events | Zero unless they return output |

My key takeaway - when a side task will read bunch of files and you only care about the conclusion, route it through a subagent so the research happens in a disposable context window and only the summary lands in yours.

## Vetting third-party skills: the threat model

Skill registries have exploded. The `npx skills` CLI is the one referenced in most talks, but to some this may set off some alarms due to the spectre of supply chain attacks.

The dynamic injection syntax means shell commands in a SKILL.md execute on your machine the moment the skill loads, before the model sees anything potentially leading to bad things.

So a SKILL.md is short. Read it, and read every script it ships, before it ever loads in a session.

There's a second, quieter failure mode: **performance**. More starts signals nothing about quality, and some widely-shared skills might make your agent worse, padding context with verbose instructions that dilute your own conventions while producing no better output - overlapping descriptions make claude load the wrong skill or miss the right one.

So my standing rule, which I happily borrowed from some of the YT [talks](https://www.youtube.com/watch?v=iQyg-KypKAA&t=1446s): never install a skill that hasn't published evidence it works, and when in doubt, write your own after taking inspiration from a 3rd paty one, if required.

## Enforcement

If you're worried about what any skill, or the model itself, might do, don't encode the boundary in prose. A "never do X" line in CLAUDE.md is a request. A `PreToolUse` hook that blocks the tool call, or a `permissions.deny` rule in settings, is a guarantee, enforced by the harness.

> Prose for guidance, hooks and permissions for guardrails.

## The onboarding loop, condensed

If I compress everything above into a ramp-up procedure for a new repo, it looks like this.

*   Run `/init` and let it draft a project CLAUDE.md, then prune it toward the 200-line target, keeping only facts every session needs.
    
*   Keep your `~/.claude/CLAUDE.md` short and purely personal.
    
*   When corrections recur, write them down: repeated mistakes go into CLAUDE.md, file-type conventions into path-scoped rules, and any section that has grown into a procedure gets extracted into a skill.
    
*   Mark side-effecting skills `disable-model-invocation: true`.
    
*   Move hard boundaries out of prose and into hooks and permission rules.
    
*   Audit context occasionally with `/memory` and `/context`, and
    
*   treat every third-party skill as unreviewed code running with your creds.
    

None of this is glamorous. Documentation hygiene done right to a colleague who forgets everything overnight but reads at superhuman speed every morning!

*References:*

*   [*Manage Claude's memory*](https://code.claude.com/docs/en/memory)
    
*   [*Extend Claude with skills*](https://code.claude.com/docs/en/skills)
    
*   [*Extend Claude Code*](https://code.claude.com/docs/en/features-overview)
    
*   [*Best practices*](https://code.claude.com/docs/en/best-practices)*, and*
    
*   *the* [*vercel-labs/skills*](https://github.com/vercel-labs/skills) *CLI.*
