Before we start: who wrote this
This course is independent of Anthropic. It is not an official course and does not reproduce Anthropic's documentation. Claude Code ships changes most weeks, so treat every file name, limit and plan mentioned here as "true when written" and check it against the current official docs at code.claude.com/docs before you standardise a team on it. Pay attention to labels. For example, agent teams are currently marked experimental and are off by default, so they are a poor foundation for a team workflow.
The one split that matters
Every customisation surface falls on one side of a line:
- Advisory context: text Claude reads and tries to follow. CLAUDE.md, rules and skills live here.
- Enforced behaviour: configuration the Claude Code client applies, whatever the model decides. Permissions, hooks and managed settings live here.
Think of it like a codebase. A CONTRIBUTING.md asks people to run the linter. A CI check makes the merge fail if they didn't. Both are useful, but only one is a guarantee.
A line such as "never edit .env" in CLAUDE.md is a request. Claude follows it most of the time, and less reliably as the file grows or the session gets long. A deny rule or a PreToolUse hook is the CI check.
The nine surfaces in one pass
| Surface | What it is | Side |
|---|---|---|
| CLAUDE.md | Always-on project instructions | Advisory |
Rules (.claude/rules/) |
Instructions split into files, optionally scoped to paths | Advisory |
| Skills | On-demand instructions and workflows in a SKILL.md |
Advisory |
| Commands | /name prompts, now merged into skills |
Advisory |
| Subagents | Isolated workers that return a summary | Neither: a worker |
settings.json |
Permissions, hooks, environment | Enforced |
| Hooks | Your script, run at a lifecycle event | Enforced |
| MCP servers | Connections to external tools and data | Neither: a capability |
| Plugins | A package of the above | Neither: packaging |
Two notes on naming. Custom commands have been merged into skills: an existing .claude/commands/deploy.md still works, and a skill at .claude/skills/deploy/SKILL.md creates the same /deploy. New work should be a skill. And managed settings are not a tenth surface: they are settings delivered by your organisation that sit at the top of the precedence order.
Worked example: sorting ten team needs
Ask one question of each need: if Claude ignores this once, is that annoying or is it an incident? Annoying means advisory. An incident means enforced.
ADVISORY (Claude reads it)
1. Use pnpm, not npm -> CLAUDE.md
2. Two-paragraph architecture overview -> CLAUDE.md
3. API handlers use our error envelope -> rule scoped to src/api/
4. The release checklist -> skill (/release)
5. How we write PR descriptions -> skill
ENFORCED (the client applies it)
6. Never read .env files -> permissions deny rule
7. Run tests without a prompt each time -> permissions allow rule
8. Format every file after an edit -> PostToolUse hook
9. Block destructive shell commands -> PreToolUse hook
10. Nobody can switch off the deny list -> managed settings
Here is what need 6 looks like on each side. The advisory version:
<!-- CLAUDE.md: a request. Usually honoured, never guaranteed. -->
- Do not read or edit .env files.
The enforced version:
// .claude/settings.json: checked by the client before the tool runs
{
"permissions": {
"deny": ["Read(./.env)", "Read(./.env.*)"]
}
}
Gotcha: enforced does not mean bulletproof. A Bash deny rule matches the command text as Claude writes it, so a wrapped or re-spelled command can slip past. Server-delivered managed settings are documented as a client-side control, not a security boundary. Use them as guardrails and keep real secrets out of reach by other means.
Trade-off: advisory surfaces cost context. CLAUDE.md is sent with every request, and the docs suggest keeping it under about 200 lines. Skill descriptions load at session start and the body loads only when the skill is used. Hooks cost nothing unless they return output.
Build it: team-surfaces.md
Create this file at the root of your repository. It is a plain document for humans; Claude Code does not load it. You will extend it in every later lesson.
# Team surfaces
Checked against official docs: 2026-10-09. Re-check before relying on any row.
| Surface | Location | Who writes it | When it loads | Side |
|---|---|---|---|---|
| CLAUDE.md | `CLAUDE.md` in the repo | Whole team, via PR | Session start, every request | Advisory |
| Rules | `.claude/rules/*.md` | Area owners | Session start, or when matching files are opened | Advisory |
| Skills | `.claude/skills/<name>/SKILL.md` | Workflow owner | Description at start; body when used | Advisory |
| Commands (legacy) | `.claude/commands/<name>.md` | Workflow owner | When invoked | Advisory |
| Subagents | `.claude/agents/<name>.md` | Workflow owner | When spawned, in its own context | Worker |
| Settings | `.claude/settings.json` | Tech lead, via PR | Applied by the client | Enforced |
| Personal settings | `.claude/settings.local.json` | Each developer, not committed | Applied by the client | Enforced |
| Hooks | `hooks` key in a settings file | Tech lead, reviewed like code | When their event fires | Enforced |
| MCP servers | `.mcp.json` at the repo root | Tech lead | Tool names at start; schemas on demand | Capability |
| Plugins | `.claude-plugin/plugin.json` plus components | Platform owner | When the plugin is enabled | Packaging |
| Managed settings | Delivered by the organisation | Admins | Top of settings precedence | Enforced |
## Experimental or beta, do not depend on yet
- Agent teams (experimental, off by default)
The "who writes it" column is the one teams skip and later regret. A hook runs a shell command on every developer's machine, so it deserves the same review as any other executable code in the repo.
Key takeaways
- This course is independent of Anthropic. Verify features, limits and plans in the current official docs, and note anything marked experimental or beta.
- CLAUDE.md, rules and skills are advisory: Claude reads them as context and usually follows them.
- Permissions, hooks and managed settings are enforced by the client, with known limits.
- Subagents, MCP servers and plugins are not on either side: they are workers, capabilities and packaging.
- Sort a need by asking whether one miss is merely annoying or an incident.
team-surfaces.mdis your running map of location, owner and load time.