Skip to content
AIAI 应用落地

8、如何写好 CLAUDE.md把项目隐性知识写成可执行规则

你有没有遇到过这种场面:Claude Code 第一次进仓库,代码写得不差,却在包管理器、测试入口、生成目录边界上反复猜错,问题往往不在模型“不会写”,而在于它还不知道你的项目到底怎么工作。每猜错一次,就是一次返工、一次 token 浪费。 不是模型笨,是你没给它入职材料。 CLAUDE.md就是那张入职卡…

J
Jasper Labs· 2026年7月31日
CLAUDE.md

INFO

💡版本说明

本文基于 Claude Code可用的官方文档整理。Claude Code 更新较快,涉及命令、加载机制和版本门槛的内容,请以文末官方资料为准。

⏱ 60 秒,先让它跑起来

markdown
# CLAUDE.md  —— paste, edit commands, commit
## Commands
- Install: `uv sync`
- Test: `uv run pytest`
- Lint: `uv run ruff check .`
- Typecheck: `uv run mypy src`
## Rules
- Python 3.12+. Prefer existing modules; do not hand-edit generated code or `.venv/`.
- After logic changes, run pytest for the affected path and report results.
## Safety
- No secrets in repo. Hard tool blocks → Settings permissions.deny (not only this file).

提交完怎么验?

  1. /context 看当前会话是否加载了这份 CLAUDE.md、占了多少上下文
  2. /memory — 打开/编辑项目指令与 Auto memory 相关文件
  3. /doctor — 诊断配置;过长文件可能被提示 trim(官方 target under 200 lines)

INFO

TIP

TIP

INFO

``

markdown
# CLAUDE.md

## Project
- Python 3.12 monorepo; API lives in `apps/api`.

## Commands
- Install: `uv sync`
- Test API: `uv run pytest apps/api/tests -q`
- Typecheck: `uv run mypy apps/api`

## Structure
- `packages/contracts`: source of truth for API schemas.
- `**/generated/**`: regenerate; do not edit by hand.

## Rules
- Schema change: edit contracts → regenerate → run API contract tests.

## Verification
- Report commands run and any skipped check with its reason.









WARNING

plain
Be careful with payments.
Run tests when needed.
Keep the code clean.

plain
## Billing changes
- Scope: `services/billing/**`
- After amount/rate changes:
  1. `uv run pytest services/billing/tests -q`
  2. `uv run pytest services/billing/tests/contract -q`
- Money uses integer minor units (no float).
- If test DB is unavailable for integration tests:
  stop and report; do not skip silently.

  • ``


TIP

INFO

`CLAUDE_CODE_NEW_INIT=1``/init``CLAUDE.local.md`

plain
Task: add `timezone` to the profile response
Expected path: `packages/contracts` → `apps/api` → contract tests
Expected commands:
  1. `make generate-api`
  2. `uv run pytest apps/api/tests/contract -q`
Do not edit: `apps/api/generated/**`
Report: changed files, commands run, failures, skipped checks

  • ````

WARNING

``

INFO

  • ``

````

plain
mkdir expense-tracker-lab
cd expense-tracker-lab
uv init --lib --name expense-tracker
uv python pin 3.13
uv add --dev pytest
mkdir -p tests

plain
New-Item -ItemType Directory expense-tracker-lab
Set-Location expense-tracker-lab
uv init --lib --name expense-tracker
uv python pin 3.13
uv add --dev pytest
New-Item -ItemType Directory -Force tests
``
plain
expense-tracker-lab/
├─ pyproject.toml
├─ .python-version
├─ src/
│  └─ expense_tracker/
│     └─ __init__.py
└─ tests/
   └─ test_report.py    # 下一步创建

WARNING

``````

``
python
import pytest

from expense_tracker.report import summarize_month

EXPENSES = [
    {"date": "2026-07-02", "category": "food", "amount_cents": 3200},
    {"date": "2026-07-03", "category": "transport", "amount_cents": 1500},
    {"date": "2026-07-20", "category": "food", "amount_cents": 2800},
    {"date": "2026-08-01", "category": "food", "amount_cents": 9999},
]

def test_summarizes_only_requested_month():
    assert summarize_month(EXPENSES, "2026-07") == {
        "month": "2026-07",
        "total_cents": 7500,
        "by_category": {"food": 6000, "transport": 1500},
    }

def test_rejects_bad_month():
    with pytest.raises(ValueError):
        summarize_month(EXPENSES, "July")


def test_rejects_float_amount():
    expenses = [
        {"date": "2026-07-02", "category": "food", "amount_cents": 32.5}
    ]
    with pytest.raises(TypeError):
        summarize_month(expenses, "2026-07")


def test_rejects_boolean_amount():
    expenses = [
        {"date": "2026-07-02", "category": "food", "amount_cents": True}
    ]
    with pytest.raises(TypeError):
        summarize_month(expenses, "2026-07")


def test_does_not_mutate_input():
    expenses = [item.copy() for item in EXPENSES]
    original = [item.copy() for item in expenses]

    summarize_month(expenses, "2026-07")

    assert expenses == original
plain
uv run pytest -q

````

``
markdown
# CLAUDE.md

## Project
- Python 3.13 library managed with uv.
- Purpose: summarize synthetic expense records by month.

## Commands
- Install: `uv sync`
- Test: `uv run pytest -q`

## Structure
- `src/expense_tracker/`: implementation.
- `tests/`: executable requirements and regression tests.

## Domain rules
- Money uses integer cents; never use float for amounts.
- Dates use ISO `YYYY-MM-DD`; month input uses `YYYY-MM`.
- Keep `summarize_month` pure; do not mutate input records.

## Change rules
- Do not add a runtime dependency for this task.
- Do not weaken or delete tests just to make them pass.

## Verification
- Run `uv run pytest -q` after changes.
- Report changed files, test result, and skipped checks.

## Safety
- Use synthetic data only. Never add real financial records.
plain
帮我实现月度支出统计,
代码写得专业一点。
plain
实现 `tests/test_report.py` 要求的功能。
开始前读取 CLAUDE.md 并说明计划;
实现后运行测试,报告改动文件和结果。
除非需求矛盾,不要修改测试。

``````
plain
请实现 `tests/test_report.py` 要求的月度支出汇总功能。

要求:
1. 开始修改前,先读取 CLAUDE.md,并用 3~5 行说明计划。
2. 实现应放在 `src/expense_tracker/report.py`。
3. 除非测试与需求矛盾,不要修改测试。
4. 完成后运行 CLAUDE.md 规定的测试。
5. 报告改动文件、测试结果,以及未执行的检查。
``

TIP

python
from datetime import date

def _parse_month(month: str) -> tuple[int, int]:
    if not isinstance(month, str) or len(month) != 7:
        raise ValueError("month must use YYYY-MM")
    try:
        parsed = date.fromisoformat(f"{month}-01")
    except ValueError as exc:
        raise ValueError("month must use YYYY-MM") from exc
    if parsed.strftime("%Y-%m") != month:
        raise ValueError("month must use YYYY-MM")
    return parsed.year, parsed.month

def summarize_month(expenses: list[dict], month: str) -> dict:
    target = _parse_month(month)
    by_category: dict[str, int] = {}
    for expense in expenses:
        spent_on = date.fromisoformat(expense["date"])
        cents = expense["amount_cents"]
        if not isinstance(cents, int) or isinstance(cents, bool):
            raise TypeError("amount_cents must be an integer")
        if (spent_on.year, spent_on.month) == target:
            category = expense["category"]
            by_category[category] = by_category.get(category, 0) + cents
    return {"month": month, "total_cents": sum(by_category.values()),
            "by_category": by_category}
``

plain
uv run pytest -q
``

INFO






TIP

WARNING


TIP


INFO

plain
# Engineering Guidelines
- Write clean and maintainable code.
- Use meaningful variable names.
- Follow industry best practices.
- Add tests when appropriate.
- Handle errors carefully.
- Keep documentation up to date.
- Avoid unnecessary dependencies.
- Make sure all changes are safe.

plain
## Commands
- Test: `uv run pytest -q`
- Lint: `uv run ruff check .`

## Rules
- Do not edit `src/generated/**` by hand.
- Add dependencies only with `uv add`.
- Bugfixes require a regression test.

## Verification
- Report commands run and skipped checks.


WARNING

plain
## Project
- Python 3.13 library; use uv for dependencies and commands.

## Domain rules
- Money uses integer cents; never use float for amounts.
- Dates use ISO `YYYY-MM-DD`; month input uses `YYYY-MM`.

## Change rules
- Explain any change to existing test expectations.

## Verification
- Run `uv run pytest -q` and report the result.

``

TIP

``
plain
# CLAUDE.md
<!-- Owner: platform-team; review quarterly.
     Do not delete the billing invariant below. -->
## Rules
- Money uses integer minor units.

``

TIP

plain
请只读审计这个仓库,为编写 CLAUDE.md 收集证据。
不要修改文件,不要安装依赖,不要执行部署或迁移。

请输出一张表,包含:
1. 安装、开发、测试、lint、类型检查、生成代码的候选命令;
2. 每条命令的证据文件和具体位置;
3. 关键目录职责、生成产物与禁止手改路径;
4. 高风险操作和需要人工确认的事项;
5. 仍无法确认的问题。

要求:没有证据的内容标记为“未知”,不要按技术栈惯例猜测。

plain
Evidence: `.github/workflows/ci.yml` runs `make test-api`
Trigger: changes under `apps/api/**`
Action: run `make test-api` from repository root
Scope: API package only
Verification: command exits 0 and test summary is reported
Failure: if test DB is unavailable, stop and report; do not skip

plain
# CLAUDE.md

## Commands
- <verified command + where to run it>

## Boundaries
- <source of truth / generated path / ownership boundary>

## Change rules
- <when X changes, do Y>

## Verification
- <change type → smallest sufficient check>
- Report failures and skipped checks with reasons.

## Safety / ask first
- <only operations that genuinely require confirmation>

WARNING

TIP

结语:好的 CLAUDE.md,是一张会改变行动的入职卡

回到开头那个问题:Claude Code 为什么会在包管理器、测试入口和生成目录上反复猜错?因为这些信息往往不在某一行代码里,而是藏在团队经验、CI 脚本和事故教训里。

写好 ,不是把仓库说明重新抄一遍,而是完成四次筛选:

  • 从证据出发:命令、路径和边界必须能在仓库或维护者确认中找到依据。
  • 只写不可稳定推导的事实:代码已经说清楚的内容,不必重复消耗上下文。
  • 把要求写成动作:范围、触发条件、验收证据和失败处理,比“注意质量”更有用。
  • 用真实任务验证:规则是否优秀,不看文件多完整,要看它有没有减少一次真实返工。

先从几十行开始。写清怎么安装、怎么测试、哪些文件不能手改、什么情况必须请示。等仓库变大,再讨论规则该放在哪里、何时加载,以及如何在 Monorepo 中避免互相污染。

DISCUSS

评论与讨论

如果这篇文章对你有帮助,或你对实现细节有不同判断,可以直接在这里继续讨论。