---
title: "How to structure your Claude Code workspace"
description: "Setting up Claude Code? A research-backed blueprint: one workspace repo, a 30-minute setup with /init and /permissions, and clear rules for when work earns its own folder or repo."
author: Agentmatik (https://agentmatik.ai)
source: https://agentmatik.ai/guides/claude-code-workspace-structure
date: "6 July 2026"
tools: "claude-code"
---
## What's inside
- The from-scratch blueprint: one workspace repo, an annotated folder tree, and a lean root CLAUDE.md
- A 30-minute setup walkthrough with the real commands: /init, /memory, /permissions, /mcp
- Growth rules: when work earns a folder - and the 3-question test for when it earns its own repo
- How Claude Code really loads context (verified against the official docs), 9 anti-patterns, and the myths to ignore

One giant workspace or a repo per project? We pulled 295 sources - the official docs, engineering write-ups, and hundreds of practitioner threads - into one answer. Here is the blueprint we use for our own automation work. You can build it from scratch this afternoon, even if today you have zero repos.

## The short version
Create one private workspace repo for everything you work on with Claude Code. Give each domain of work its own subfolder with its own CLAUDE.md as it appears, launch Claude Code from the subfolder for focused sessions and from the root for cross-cutting work, and give something its own repo only when it has a genuinely different lifecycle, audience, or access boundary - a deployable product, a knowledge base with its own review flow, code another team owns, or client work under NDA that needs hard isolation.

Per-role or per-function repos almost always fail the same way: you live in one of them, the rest go stale, and the "back everything up to GitHub" goal silently breaks because nobody pushes repos they never open.

## Start here: one private workspace repo
On day one you need exactly one repo. Create it, make it private, and treat it as the home for every file you and Claude touch that does not obviously belong somewhere else:

```
mkdir ~/code/workspace
cd ~/code/workspace
git init
```

Here is what it grows into. You do not create all of this today - the point of the blueprint is knowing where things will go when they appear:

```
workspace/                    # ONE private repo
├── CLAUDE.md                 # lean root: what this is, the map, global rules
├── .claude/
│   ├── settings.json         # permissions (deny .env reads), hooks - committed
│   └── skills/               # workspace-wide skills
├── .mcp.json                 # root-scope MCP servers, ${ENV_VAR} refs only
├── .gitignore                # .env, big binaries, caches, .claude/worktrees/
├── automations/              # domain A - your main domain can be the root itself
├── marketing/                # domain B
│   ├── CLAUDE.md             # scoped: what lives here, conventions
│   ├── .mcp.json             # domain MCP servers (load when launched here)
│   └── .claude/skills/       # domain skills (apply when working here)
├── clients/<name>/           # per-client folders, own CLAUDE.md each
├── docs/  guides/  plans/    # workspace-wide knowledge
└── tools/  scripts/          # shared deterministic tooling
```

Separate repos live alongside it - only what passes the 3-question test below:

```
~/code/
├── workspace/                # the monorepo above
├── product-site/             # each deployable product: its own repo
├── team-shared-repo/         # repos other people push to
└── knowledge-base/           # SSOT repos with their own review flow
```

## The setup walkthrough (about 30 minutes)
- **1. Launch Claude Code in the folder.** Run **claude** inside ~/code/workspace. The directory you launch from decides which [settings](https://code.claude.com/docs/en/settings) and [project MCP servers](https://code.claude.com/docs/en/mcp) load, so the workspace root is home base from the first minute.
- **2. Generate a starter CLAUDE.md with /init.** The [/init command](https://code.claude.com/docs/en/commands) scans the folder and bootstraps a CLAUDE.md for you; set **CLAUDE_CODE_NEW_INIT=1** to get the newer interactive flow that asks about your setup instead of guessing. Treat the output as a draft, not a final file.
- **3. Cut the draft down to a map, not a manual.** Aim for well under 200 lines - the [official guidance](https://code.claude.com/docs/en/claude-directory) and the single most repeated community lesson (the best root files are [shockingly small](https://www.humanlayer.dev/blog/writing-a-good-claude-md)). Keep four things: one paragraph on what the workspace is, a table of top-level folders, your global rules (secrets, style, logging), and pointers to deeper docs instead of their content. Refine it anytime with [/memory or the # shortcut](https://code.claude.com/docs/en/memory). A good example: one practitioner runs his whole [personal OS](https://amankhan1.substack.com/p/how-carl-set-up-his-personal-os-in) on a root file under 100 lines.
- **4. Lock down secrets with /permissions.** Add [deny rules](https://code.claude.com/docs/en/permissions) on file reads for .env and anything secret-shaped - deny beats allow, and a deny rule is the real protection; an ignore-style exclusion alone is not. Keep the actual .env gitignored, with a secret manager as the source of truth.
- **5. Wire tools with /mcp.** Add MCP servers to a project [.mcp.json](https://code.claude.com/docs/en/mcp) so they are versioned with the workspace - and reference credentials as ${ENV_VAR}, never pasted values.
- **6. Write the .gitignore before the first big commit.** .env, caches, .claude/worktrees/, and every folder that will ever hold video, design exports, or generated assets - big binaries go to cloud storage, not git. One careless git add -A can try to swallow gigabytes.
- **7. Commit and push.** Create the private GitHub remote and push. From now on the workspace is your working memory: treat an unpushed workspace as an incident.

[[newsletter]]

## Growing it: folders first, repos only at a boundary
### A second kind of work earns a folder
When a genuinely different domain shows up - say marketing next to your build work - it gets a subfolder with its own CLAUDE.md (what lives here, domain conventions, which root rules apply with extra force - additive to the root, never contradictory). If the domain needs its own tools, give it a domain .mcp.json and [directory-scoped skills](https://code.claude.com/docs/en/skills).

Then adopt the habit that makes the whole structure pay off:

**cd workspace && claude** gives you a root session: the full map, cross-domain work, no domain MCP servers.

**cd workspace/marketing && claude** gives you a marketing session: the root CLAUDE.md plus the marketing CLAUDE.md, MCP servers, and skills. Every other domain stays out of the way - which is exactly the lean-context behavior [Anthropic's context engineering guidance](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents) pushes for.

For parallel sessions on the same repo, use [git worktrees](https://code.claude.com/docs/en/worktrees) - keep them under .claude/worktrees/ and gitignore that folder. And when you need another repo's code in context, **claude --add-dir ../other-repo** beats copying files around.

![Diagram: domains earn folders inside the workspace; a separate repo only when lifecycle, audience, or access says yes](/guides/claude-code-workspace-structure/folders-vs-repos.jpg)

### Something earns its own repo only at a boundary
A separate repo is justified only if at least one answer is yes:

- **Lifecycle** - does it deploy, release, or version independently? If yes: products, websites, published packages, and browser extensions get their own repo.
- **Audience** - do other people (or other AI agents) need access to it? If yes: team repos, client-shared repos, and public projects get their own repo.
- **Access boundary** - would mixing it in violate privacy, an NDA, or compliance? If yes: personal data, client-confidential work, and regulated code stay separate.

Everything else - notes, plans, guides, scripts, exported configs, research, client working files only you touch - stays in the one workspace repo.

### Why the one-workspace direction wins
- **Cross-cutting context is the whole point.** A coding agent can update an API contract, regenerate types, fix the call sites, and test end to end in one session - the reason [AI-era repo guidance](https://www.augmentcode.com/learn/monorepo-vs-polyrepo-ai-s-new-rules-for-repo-architecture) tilts toward monorepos. Split repos force you to ferry context between sessions by hand.
- **Lazy loading solves the pollution fear.** Subfolder CLAUDE.md files do not load at launch - they load only when Claude works with files in that subtree ([official behavior](https://code.claude.com/docs/en/memory)). A big workspace does not mean a big context.
- **One backup to keep healthy.** Ten repos means ten push disciplines. In practice, the repos you do not open daily rot unpushed.
- **Practitioners who tried both agree.** Teams that made their monorepo agent-ergonomic report [large velocity gains](https://www.getbasis.ai/blogs/how-we-made-our-monorepo-ergonomic-for-agents); the strongest counter-arguments are about huge multi-team codebases ([CI cost, team autonomy](https://code.claude.com/docs/en/large-codebases)) - not about a personal or agency workspace.

## How Claude Code actually loads context
This is the "why" behind the blueprint - and several popular blog claims about it are wrong (see the myth-busting section at the end). Every point links to the doc that verifies it.

- **1.** At launch, Claude Code loads your global ~/.claude/CLAUDE.md plus every CLAUDE.md from the launch directory up the ancestor chain - always in context ([memory docs](https://code.claude.com/docs/en/memory)).
- **2.** Subfolder CLAUDE.md files lazy-load: they enter context only when Claude reads or edits files in that subtree ([memory docs](https://code.claude.com/docs/en/memory)). This is what makes a large workspace cheap.
- **3.** Memory files concatenate - they do not override each other ([memory docs](https://code.claude.com/docs/en/memory)). Write nested files so they add scope-specific detail instead of contradicting the root.
- **4.** .claude/settings.json is not inherited from parent directories - it loads from the directory you start Claude in ([settings docs](https://code.claude.com/docs/en/settings)), so a subfolder session does not get the root folder's settings automatically.
- **5.** .mcp.json is read from the launch directory too ([MCP docs](https://code.claude.com/docs/en/mcp)). A marketing/.mcp.json loads when you start Claude inside marketing/ - not when you start at the workspace root.
- **6.** Nested .claude/skills/ folders do apply when Claude works inside that subfolder, even if the session started at the root ([skills docs](https://code.claude.com/docs/en/skills)).
- **7.** additionalDirectories in settings grants file access only - it does not load that directory's CLAUDE.md or skills ([settings docs](https://code.claude.com/docs/en/settings)).
- **8.** Permissions: deny beats allow, and a deny rule on file reads is the real protection for secrets ([permissions docs](https://code.claude.com/docs/en/permissions)).
- **9.** Session transcripts are stored in plaintext under ~/.claude/projects/ ([.claude directory anatomy](https://code.claude.com/docs/en/claude-directory)). Anything Claude reads can end up there - this matters for client isolation (see the tiers below).
- **10.** claudeMdExcludes exists to skip specific CLAUDE.md files in very large monorepos ([large-codebases docs](https://code.claude.com/docs/en/large-codebases)).

## Git and backup rules that save you later
- **Private repo, push discipline.** The workspace is your working memory - treat an unpushed workspace as an incident. Multi-repo setups fail exactly here.
- **Secrets never in git.** Env-var references in [.mcp.json](https://code.claude.com/docs/en/mcp), a gitignored .env as the local cache, a secret manager as the source of truth - and a pre-commit secret scan such as gitleaks.
- **Big binaries never in git.** Videos, design assets, and exports go to cloud storage; gitignore those folders. One careless git add -A can try to swallow gigabytes.
- **Archive, do not delete.** When retiring old repos, archive them on GitHub - the history stays readable for free and every change is reversible.
- **History is a leak surface.** When folding an old repo's content in, import content only (rsync, not a git merge) if its history ever contained secrets - and rotate anything that was committed.

These are not hypothetical risks. In one workspace we audited, 44 production skills existed only inside an uncommitted git worktree - one prune command away from disappearing, and invisible to the "everything is on GitHub" backup story. In another, a pre-commit scan caught 16 live tokens sitting in exported workflow configs before they reached GitHub. Exported configs, not source code, are the classic leak vector.

## Client work: three isolation tiers
The one place where "just use the workspace" needs qualification. Tier your clients by sensitivity:

- **Tier 1 - normal client work (the default).** A clients/<name>/ folder inside the workspace with its own CLAUDE.md and secrets via env references. Fine for most agency work where you are the only operator.
- **Tier 2 - confidential (NDA, competing clients).** A separate private repo per client. Launch Claude only from inside it, with a per-repo [.mcp.json](https://code.claude.com/docs/en/mcp) so client credentials never load anywhere else. And remember the plaintext transcripts: a root-launched session can read every client folder, so do not start root sessions if browsing across clients would already be a breach.
- **Tier 3 - regulated or high-sensitivity.** A dedicated devcontainer or VM per client with allowlisted egress; nothing shared.

Mixed-tool teams: if collaborators use other coding agents too, keep the canonical instructions in AGENTS.md and make CLAUDE.md a one-line import of it ([memory docs](https://code.claude.com/docs/en/memory)).

## Already have work scattered across several repos?
Then consolidate content, not history: rsync the files into workspace subfolders (scan each old repo for committed secrets first - findings mean rotate the keys and never merge that git history), then archive the old repos on GitHub instead of deleting them, so everything stays reversible. And if you have many live code repos you cannot merge - deployed products, CI you must not touch - skip the merge entirely: a [virtual monorepo](https://medium.com/devops-ai/the-virtual-monorepo-pattern-how-i-gave-claude-code-full-system-context-across-35-repos-43b310c97db8) (a parent folder cloning them by domain, with a top-level CLAUDE.md system map) or an identical "repository ecosystem" table in every repo's CLAUDE.md gives Claude the full-system view without moving anything.

## Nine anti-patterns we keep seeing
- **The dumping-ground CLAUDE.md.** One 900+ word root file mixing conventions, project state, and reminders. Signal-to-noise collapses and the instructions get ignored ([keep it small](https://www.humanlayer.dev/blog/writing-a-good-claude-md)). Split it and push detail down.
- **Per-role repos.** The role you do 90% of the time absorbs everything; the rest die unpushed. Domains earn folders, not repos.
- **Over-engineered .claude/ scaffolding.** Elaborate rules, commands, and subagent trees built up front rot fast - one practitioner deleted 60% of theirs within four months. Add structure when a pain repeats, not before ([best practices](https://code.claude.com/docs/en/best-practices)).
- **Secrets in .mcp.json or exported configs.** The most common real leak. Env references plus pre-commit scanning.
- **Unignored binary folders.** One git add -A away from an 11 GB commit.
- **Root-launched everything.** Never using subfolder sessions means every session pays for every domain's context and MCP servers - the opposite of [effective context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents).
- **Trusting "deeper CLAUDE.md overrides shallower".** It concatenates ([memory docs](https://code.claude.com/docs/en/memory)). Contradictory instructions produce coin-flip behavior.
- **A git repo in your home directory.** It shadows every repo beneath it and confuses tooling.
- **Mirroring live systems into the repo as docs.** Exports go stale and leak tokens. Declare the live system the source of truth and export deliberately.

## Myths that failed verification
Popular claims we checked against the official docs and could not confirm - do not build your structure on these:

- **"A deeper CLAUDE.md takes priority over the root on conflict."** Wrong - the [memory docs](https://code.claude.com/docs/en/memory) describe concatenation, with no override semantics.
- **"CLAUDE.local.md loads last, so it wins."** A [deprecated mechanism](https://code.claude.com/docs/en/memory) - use imports of untracked files instead.
- **"The .claude folder controls about 80% of Claude Code's capability."** An invented statistic - the [.claude directory docs](https://code.claude.com/docs/en/claude-directory) make no such claim.
- **"CLAUDE.md is often ignored, so inject everything via hooks."** Overstated - a lean, well-structured CLAUDE.md is followed ([best practices](https://code.claude.com/docs/en/best-practices)). Hooks are for enforcing hard rules, not a workaround for bloat.
- **"Claude Code has no project boundaries, so you need an external memory tool."** Overstated - workspace trust, [launch-directory settings](https://code.claude.com/docs/en/settings), and directory-scoped CLAUDE.md files are exactly those boundaries.

