all topics

Workflow

Claude Projects

Two surfaces, two persistence models, one name. Understanding the difference is the starting point for using either one well.

TLDR;

"Project" means two different things in the Claude ecosystem. On claude.ai, a Project is a web UI feature: a named container where you store persistent instructions and reference documents, shared across all conversations in that project. In Claude Code, a project is your working directory — the .claude/ folder, CLAUDE.md, memory files, settings, and skills that together define how Claude behaves in that codebase.

The two are complementary, not competing. Understanding what each one does — and what it cannot do — determines how much friction you carry in your daily workflow. Developers who conflate them end up duplicating context in both places, or wondering why changes they made in one aren't reflected in the other.

Side-by-side comparison of claude.ai Projects and Claude Code Projects. Left side purple: claude.ai Project contains project instructions you write, knowledge base files uploaded as docs, conversations not shared across chats, and team sharing with Can use or Can edit permissions. Claude reads context but cannot update it. Right side green: Claude Code Project contains CLAUDE.md auto-loaded always, .claude/memory written by Claude, settings.json with permissions and hooks committed to git, and skills plus rules version-controlled. Claude reads and writes context, shared via git.
The critical difference is who writes the context. In claude.ai Projects, you maintain everything and Claude reads it. In Claude Code Projects, Claude can write its own memory — your notes and Claude's notes coexist on disk, version-controlled alongside your code.

claude.ai Projects

claude.ai Projects are available on Pro and higher plans. They give you a persistent workspace that survives across individual conversations: fixed instructions that load for every chat in the project, and a file-based knowledge base Claude can reference via RAG (Retrieval Augmented Generation).

Creating a Project

From claude.ai, click Projects in the left sidebar, then + New Project. Give it a name and description. The name and description are for your organisation — Claude does not see them.

Project Instructions

Instructions are the persistent context that shapes every conversation in the project. Think of them as a standing brief: the role Claude should take, the format you expect responses in, constraints that always apply. They are prepended to every conversation in the project without you having to paste them.

# Example project instructions for a development consultancy

You are a senior code reviewer working on a PHP 8.3 web application.
Always respond with specific file and line references.
Assume the reader is a professional developer — skip beginner context.
Flag security issues before functional issues.
When suggesting changes, show the minimal diff, not the whole file.

Keep instructions focused. Instructions that try to cover every possible case end up being ignored because the relevant part is buried. A 100-word instruction that Claude actually applies is more valuable than a 1,000-word one it partially skips.

The Knowledge Base

The knowledge base holds reference documents: architecture decision records, API specifications, style guides, onboarding docs. Uploaded files are indexed and retrieved via RAG — Claude pulls relevant passages rather than reading every document in full. When your project knowledge approaches the context limit, RAG mode expands capacity automatically on paid plans.

The knowledge base is intentionally static. Claude cannot update or append to it during a conversation. If a document changes, you upload a new version manually. This is the key limitation of claude.ai Projects for active development work: the human is always the integration layer between what Claude learns and what the project knows.

Conversation history is not shared across chats within a project. If you establish context in Monday's conversation, Tuesday's conversation starts fresh. The only persistence is what you put in project instructions and the knowledge base.

Team Sharing

On Claude for Work (Teams/Enterprise) plans, projects can be shared with colleagues at two permission levels:

Can use   — view instructions, start conversations, read knowledge base
             cannot modify instructions, files, or member settings

Can edit  — full access: modify instructions, upload files, manage members

Sharing is done by email or by setting organisation-wide visibility. Shared projects are useful for team-wide reference bases — a shared API specification, a common coding style guide, or a product brief that everyone working on a feature should have in context.

Claude Code Projects

In Claude Code, "project" refers to everything inside the .claude/ directory at your project root, plus CLAUDE.md. These files define how Claude behaves in that specific codebase. They are plain files on disk, committed to version control, and loaded automatically at the start of every Claude Code session in that directory.

The Full Directory Structure

project-root/
├── CLAUDE.md                    # always loaded — project instructions
├── CLAUDE.local.md              # personal additions — gitignored
└── .claude/
    ├── settings.json            # team config — committed
    ├── settings.local.json      # personal overrides — auto-gitignored
    ├── memory/                  # Claude's own notes — see below
    │   ├── MEMORY.md            # index of all memory entries
    │   ├── user_prefs.md        # how you like to work
    │   ├── feedback.md          # corrections Claude remembers
    │   └── project.md           # current goals, decisions, state
    ├── skills/                  # reusable slash commands
    │   └── security-check/
    │       └── SKILL.md
    └── rules/                   # conditional instructions by file path
        └── db-layer.md          # loaded only when touching DB files

CLAUDE.md vs. Memory vs. Skills

Each component serves a distinct purpose. Mixing them produces context that is harder to maintain and costs more tokens than necessary.

CLAUDE.md        You write this. Static facts about the project:
                 how to run it, architecture, conventions, what to avoid.
                 Loaded every session. Keep it under 300 tokens.

.claude/memory/  Claude writes this. Learned context across sessions:
                 your preferences, past decisions, corrections, current goals.
                 MEMORY.md index loaded at startup; topic files on demand.

.claude/skills/  You write this (Claude can invoke). Reusable workflows:
                 security audits, PR summaries, deploy checklists.
                 Descriptions loaded at startup; full content on invocation.

.claude/rules/   You write this. Conditional instructions by file path:
                 DB layer rules load only when touching DB files.
                 Rules without paths load at startup (treat like CLAUDE.md).

settings.json vs. settings.local.json

settings.json is the team configuration — committed to git and shared with every developer who clones the repository. It holds the permissions your team has agreed Claude should have in this codebase, the hooks that run automatically, and any shared model preferences.

settings.local.json is automatically added to .gitignore by Claude Code. It holds your personal overrides: tools you have pre-approved for your own machine, personal model preferences, or local paths that don't exist on other developers' machines. It takes precedence over settings.json.

Vertical precedence diagram showing five settings levels from highest to lowest. Level 1 red: Managed enterprise settings, cannot be overridden. Level 2 orange: Command-line flags, session only. Level 3 green highlighted: .claude/settings.local.json, personal project overrides, auto-gitignored. Level 4 green: .claude/settings.json, team config, committed. Level 5 blue: ~/.claude/settings.json, global user defaults for all projects. Note: array settings merge across all levels, scalar settings use most specific value.
Settings closest to the session win. Your personal local settings override the team settings, which override your global defaults. Array settings like permissions.allow merge across all levels — so a global allow rule doesn't disappear when a project setting exists.

What Loads at Startup

Two-panel diagram. Left panel green shows what auto-loads at session start: CLAUDE.md from all directory levels, CLAUDE.local.md, rules without path constraints, the first 200 lines of MEMORY.md, skill descriptions but not full content, and all hooks and settings. Right panel blue shows what loads on demand: path-gated rules when matching files are touched, memory topic files when relevant, full skill content when invoked, skill supporting files when referenced, and files Claude reads during tasks.
Startup cost is fixed; on-demand cost scales with what you actually do. The split is deliberate — skill descriptions tell Claude what workflows are available without loading all the instructions until you need them. Run /context in any session to see a live token breakdown.

Step-by-Step: Setting Up a Claude Code Project

Step 1 — Write CLAUDE.md

Start with the minimum that reliably orients Claude in a fresh session. Answer three questions: how do I run this project, what should I know about its structure, and what must I never do here.

# CLAUDE.md skeleton

## Run
docker compose up          # serves at http://localhost:8080
docker compose up --build  # after Dockerfile changes

## Architecture
No framework. Apache → .htaccess rewrites → PHP files.
Topics registered in includes/topics.php.
Colors exclusively in css/tokens.css — never inline.

## Do not
- Add npm, composer, or any build step
- Store credentials in source files — use includes/auth.php (web-blocked)

Keep it under 300 tokens. Everything else belongs in a task-specific file or in memory, loaded when it is actually needed.

Step 2 — Configure settings.json

Set the permissions your team agrees Claude should have, and wire any hooks that should fire automatically. This file is committed — agree on it with collaborators before relying on it.

{
  "permissions": {
    "allow": [
      "Bash(docker compose *)",
      "Bash(git diff*)",
      "Bash(git log*)",
      "Bash(git status)"
    ],
    "deny": [
      "Read(includes/auth.php)",   // credential file
      "Read(.env*)",               // environment secrets
      "Bash(git push*)"            // require human confirmation
    ]
  },
  "hooks": {
    "PostToolUse": [{
      "matcher": "Write|Edit",
      "hooks": [{ "type": "command", "command": "python .claude/update_timestamp.py" }]
    }]
  }
}

Step 3 — Add settings.local.json for personal overrides

This file never gets committed. Use it for tools you want pre-approved on your own machine without requiring team agreement.

{
  "permissions": {
    "allow": [
      "Bash(php -r *)",    // PHP available on this machine
      "Bash(open *)"       // macOS — open files in browser
    ]
  }
}

Step 4 — Initialise memory

Create the memory directory and an empty index. Claude will populate entries over time, but starting with a clear index prevents it from writing to an unexpected location.

mkdir -p .claude/memory
# Create an empty index
echo "# Memory Index\n" > .claude/memory/MEMORY.md

Step 5 — Set up a .gitignore entry

Claude Code auto-ignores settings.local.json, but you should also protect CLAUDE.local.md and any machine-specific files you add to .claude/.

# .gitignore additions
CLAUDE.local.md
.claude/settings.local.json   # auto-ignored, but explicit is clear

Step 6 — Verify with /context

Start a Claude Code session and run /context. It shows a live breakdown of token usage per category. If CLAUDE.md is consuming more than 300–400 tokens, trim it. If rules are loading unexpectedly, check their paths: frontmatter.

Tips and Good Practices

Keep CLAUDE.md surgical

Every line in CLAUDE.md costs tokens on every session, forever. The right test: if you removed a line, would Claude's output degrade within a single session? If not, the line belongs somewhere else — a rule file, the knowledge base, or not at all. Three accurate sentences outperform ten vague ones.

Use rules/ for context that only matters sometimes

If you have instructions that only apply when Claude is touching a specific layer of the code — database migrations, authentication, payment processing — put them in a rules file with a paths: constraint. They load when relevant and cost nothing when they are not.

---
# .claude/rules/auth-layer.md
paths: "includes/auth.php,sign-in*.php"
---

Auth files are security-critical. Before any edit:
1. Confirm the change does not weaken session handling
2. Verify credentials are not hardcoded — read from includes/auth.php
3. Confirm session_regenerate_id(true) follows any successful login

Deny credential files explicitly

Even if credentials are in a correctly web-blocked file, you can add a deny rule in settings.json so Claude never reads them into its context — and therefore never risks including them in generated output or tool calls:

"deny": [
  "Read(includes/auth.php)",
  "Read(.env)",
  "Read(.env.*)",
  "Read(**/secrets/**)"
]

Periodic memory cleanup

Memory files accumulate entries that were true last month but are not true now. A project-state memory written during a sprint that finished three weeks ago does not help Claude — it actively misleads it. Schedule a brief review every time you start a new major piece of work:

Memory audit — run at the start of each new sprint or feature:
  [ ] Open .claude/memory/MEMORY.md and read the index
  [ ] Delete any project_*.md entries that describe completed or abandoned work
  [ ] Update project_*.md entries that describe the current sprint goals
  [ ] Verify user_*.md and feedback_*.md entries still reflect how you work
  [ ] Run /context to confirm startup token cost is reasonable

Periodic security evaluation

Project configuration files accumulate permissions over time. A permission that was temporarily added for a migration task may still be there six months later. Review regularly:

Security audit — run when the project has been active for 30+ days:
  [ ] Review settings.json allow list — remove permissions no longer needed
  [ ] Review settings.local.json — same
  [ ] Verify deny list covers all credential and secret files
  [ ] Check CLAUDE.md for any hardcoded values that should be references
  [ ] Check memory files for any stored values that look like secrets
  [ ] Review hooks — confirm they only run intended commands
  [ ] Run /security-check (if you have the skill installed) on .claude/ itself

What to commit vs. what to keep local

Commit (shared with team):
  CLAUDE.md                    ✓ project instructions
  .claude/settings.json        ✓ team permissions + hooks
  .claude/skills/              ✓ team workflows
  .claude/rules/               ✓ conditional instructions
  .mcp.json                    ✓ shared MCP servers

Keep local (never commit):
  CLAUDE.local.md              ✕ personal preferences
  .claude/settings.local.json  ✕ auto-gitignored by Claude Code
  .claude/memory/              ✕ Claude's personal notes about your session

claude.ai Projects vs. Claude Code — Choosing

The two are not alternatives — they are tools for different stages of work. The question is not which one to use but what belongs in each.

Use claude.ai Projects for:
  Shared reference material — API specs, design docs, onboarding guides
  Non-technical team members who need consistent AI behaviour
  Conversations about documents rather than code
  Sharing context with stakeholders who don't use Claude Code

Use Claude Code Projects for:
  All active development work — editing, testing, refactoring
  Anything that needs to run the project (builds, tests, migrations)
  Workflows that span multiple sessions (multi-day features)
  Teams that want project config version-controlled alongside code

Use both when:
  Your team uses claude.ai for design review and Claude Code for implementation
  You want a shared knowledge base (claude.ai) + per-developer workflow (Claude Code)
  The project has non-developer stakeholders plus a development team
The most durable setup: a tight CLAUDE.md that describes the codebase for developers, a claude.ai Project that holds the design brief and product spec for the broader team, and a memory directory that grows incrementally as Claude learns how you specifically like to work. Each layer holds exactly what it is best suited to hold — and nothing else.

Quick Reference

claude.ai Project setup:
  [ ] claude.ai → Projects → New Project
  [ ] Write focused instructions (<500 words) — role, format, constraints
  [ ] Upload reference documents to knowledge base
  [ ] Share with team at appropriate permission level
  [ ] Review and update instructions when project direction changes

Claude Code Project setup:
  [ ] Write CLAUDE.md — run commands, architecture, do-not list
  [ ] Create .claude/settings.json — allow + deny lists, hooks
  [ ] Create .claude/settings.local.json — personal overrides only
  [ ] mkdir .claude/memory + empty MEMORY.md index
  [ ] Add CLAUDE.local.md to .gitignore
  [ ] Run /context to verify startup token cost

Ongoing maintenance:
  [ ] Memory audit at start of each sprint — delete stale project_*.md
  [ ] Security audit every 30 days — review allow/deny lists
  [ ] CLAUDE.md review after major architectural changes
  [ ] Trim knowledge base when documents become outdated
top