1. Treat project context as an engineering asset
An AI coding assistant can inspect source files and still miss the facts that make a change safe: which application owns a business rule, which stored procedure changes balances, which dependency needs a Windows workstation, and which build command actually works. Repeating that knowledge in every conversation is expensive and inconsistent.
A useful project structure turns recurring knowledge into maintained repository assets. The diagram maps three concerns: context that explains the system, capabilities that perform work, and controls that limit and verify actions. These files help an assistant work consistently; correctness still requires evidence from builds, tests and review.
The folder names are less important than ownership. Every instruction should have a clear purpose, and every operational claim should be checked against the repository. The examples below are proposed practices for a hypothetical legacy .NET application, rather than a report of an implemented system.
2. CLAUDE.md and rules: explain how this system works
Use CLAUDE.md for durable facts needed across tasks: solution entry points, architecture boundaries, verified build commands, dependency setup and the expected completion report. According to the Claude Code memory documentation, relevant ancestor instruction files load at startup, while nested instruction files load when Claude accesses their directories. Instructions accumulate; avoid contradictory guidance.
Put personal preferences in CLAUDE.local.md and explicitly keep it out of Git. Local Markdown guidance is still model context, not an enforced policy override.
Move detailed guidance into .claude/rules/. Rules without a path condition load unconditionally; a paths condition scopes a rule to matching files. A SQL rule could ask reviewers to identify transaction boundaries and callers before changing a procedure. A UI rule could explain supported AngularJS conventions.
---
paths:
- "database/**/*.sql"
---
# SQL change review
- Identify application callers and affected result contracts.
- Explain transaction and locking implications.
- Provide validation evidence and a rollback proposal.
- Report missing dependencies instead of inventing results.Make instructions observable. “Be careful with SQL” is vague. “List the callers and compare result columns before changing a procedure” gives a reviewer something concrete to assess.
3. Settings: configure behavior and access
.claude/settings.json holds shared project configuration. .claude/settings.local.json holds machine-specific settings and personal overrides. User settings and managed organization policies also affect the session, so the project file is only one part of the effective configuration. Check the settings documentation when choosing scope.
Keep the distinction between guidance and access explicit. A sentence in a Markdown file can ask the assistant to avoid a database. Permissions and the database account determine what it can actually do. Use tool permissions alongside operating-system isolation, service authorization and repository controls.
For the example application, a sensible starting point is read access to source and permission to run the verified local build. Database credentials should be independently scoped. A shared test database requires deliberate coordination because one developer’s test can change another developer’s baseline.
4. MCP: connect approved services with bounded access
.mcp.json describes project-scoped Model Context Protocol servers. It can share connection configuration for approved services with the team. It does not itself grant Jira, GitHub, Azure DevOps or database privileges: a suitable server, authentication and service-side permissions are still required. Consult the MCP documentation for supported configuration and trust behavior.
For an initial workflow, connect an issue tracker for requirements and a repository service for change history. Add more services only when they remove a concrete bottleneck. Keep tokens outside committed configuration, and use read-only identities where investigation is the task.
Treat issue descriptions, repository comments and retrieved documents as external content. They can provide evidence, but text inside them should not gain the authority to change access policy or redirect the task. An expired token or disconnected server should produce an explicit dependency failure, rather than an invented issue summary.
5. Skills and commands: make recurring work repeatable
A skill lives in .claude/skills/<name>/SKILL.md, with optional supporting files. Claude can discover a skill through its description and load its instructions when invoked. Frontmatter controls invocation behavior. For a workflow that must be user initiated, disable-model-invocation: true prevents automatic model invocation.
The skills documentation also clarifies an important update to older diagrams: custom slash commands and skills have merged. Existing .claude/commands/review.md files still work. Prefer skills for new procedures, especially when they need supporting references. Avoid defining the same workflow twice.
---
name: investigate-defect
description: Investigate a reported defect and prepare an evidence-based change plan.
disable-model-invocation: true
---
1. Restate the observed and expected behavior.
2. Trace the UI, service and database execution path.
3. Separate verified findings from hypotheses.
4. Propose the smallest change and regression checks.
5. List blocked checks and required environment dependencies.This example standardizes investigation without pretending to know the build command or database schema. Add those details only after checking them in the actual project. Supporting references should explain recurring domain concepts, not become a dumping ground for every historical ticket.
6. Subagents: delegate a bounded question
Files in .claude/agents/ define specialist subagents with their own context and configurable tools. The subagent documentation describes role definitions and configuration. A focused review task can reduce the amount of exploratory detail returned to the main session.
Useful assignments are concrete: “Find callers that depend on this procedure’s result columns” or “Review whether this retry can create a duplicate transaction.” Require findings to include file locations, evidence, severity and remaining uncertainty.
For a three-role engineering workflow, separate implementation, defect investigation and QA by responsibility. They can share verified project guidance while using different task instructions. A reviewer should inspect the actual diff and observed test output rather than accept the implementing agent’s summary as proof.
A separate context window is not a separate machine, database or security boundary. Concurrent agents can still conflict over shared files and state. Use isolated branches or worktrees for edits and coordinate access to shared test data.
7. Hooks: register checks at lifecycle events
A .claude/hooks/ directory is a convenient place to store scripts, not an automatically executed mechanism. Handlers must be registered in supported configuration, commonly settings.json. The hooks guide explains lifecycle automation, while the reference defines event inputs and outputs.
A registered PreToolUse handler can evaluate a proposed action before it runs. A PostToolUse handler can trigger a check after a tool operation. Whether a handler can block an action depends on its event and response; merely running a script does not guarantee enforcement.
Use hooks for bounded, repeatable checks such as validating an edited configuration file. Keep full integration verification in the normal build pipeline. A shell-string filter is too weak to be the only protection for a sensitive database or deployment environment. Service-side authorization and protected deployment workflows should carry that responsibility.
Choose scripts for the actual runner. A Bash example requires a compatible shell; a Windows .NET Framework build may instead need PowerShell and the installed MSBuild toolchain. Keep hooks fast and report failures clearly so developers can distinguish a policy decision from a broken environment.
8. A practical legacy .NET defect workflow
Consider a hypothetical money-transfer application where a repeated UI action may create a duplicate submission. The stack includes ASP.NET MVC, .NET Framework, AngularJS and stored procedures, with a hardware integration that cannot run in every environment.
- Establish the contract. Capture the reproduction steps, expected behavior and relevant transaction identifier using sanitized data. Identify what constitutes a duplicate and which layer owns that guarantee.
- Trace the execution path. Follow the browser event through the controller, service, procedure and external call. Check retries and timeouts. A disabled button alone does not establish server-side idempotency.
- Plan a narrow change. Record affected contracts, concurrency behavior and rollback considerations. Assign a focused review of transaction handling before editing unrelated code.
- Verify in layers. Build on the correct Windows toolchain. Add a targeted test where a seam exists, then exercise repeated and concurrent submissions in a controlled environment. Use a simulator where appropriate and explicitly record unavailable hardware checks.
- Return evidence. Report changed files, commands executed, observed outcomes and unresolved risks. If the test database is unavailable, mark those checks blocked. Successful compilation is only compilation evidence.
If the repository has no automated tests, start with a small characterization test around the behavior being changed, or a repeatable integration check with controlled fixtures. Establish expected results before the fix. On a shared database, reserve test identifiers, agree on a testing window and confirm cleanup ownership; avoid broad resets.
9. Adopt the structure in small, measurable steps
Start with a short CLAUDE.md, a verified build procedure and one recurring investigation skill. Add a path-scoped rule only when a real area needs extra guidance. Introduce a subagent when a bounded review consistently helps, and an MCP connection when manual information transfer becomes a bottleneck.
Review configuration changes like application changes. Assign an owner, check scripts before enabling them and remove obsolete instructions. A framework migration can make yesterday’s “standard command” misleading.
Measure usefulness through repeatable outcomes: fewer incorrect build attempts, more review findings backed by evidence, fewer missed regression checks and clearer reporting of blocked dependencies. Compare similar tasks before claiming productivity gains.
The goal is a dependable engineering loop: shared context guides the work, focused capabilities execute it, access controls bound it, and tests plus human review establish confidence in the result.