You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(claude-md): link to /review-changes; condense write-time rules (#159)
Point reviewers at the `/review-changes` skill for the full detection
checklist, and collapse the per-rule sections (Imports / Type Annotations
/ Multi-Value Returns / Single Source of Truth / Dead Code) into a
shorter bulleted "General principles" list. Project-specific rules
(Internal vs External Modules, Testing) stay in full.
Copy file name to clipboardExpand all lines: CLAUDE.md
+9-18Lines changed: 9 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,8 @@ uv run pytest tests/ # Run Python tests
12
12
13
13
## Code Conventions
14
14
15
+
The full review-time detection checklist (with worked examples and post-hoc smell patterns) lives in the [`/review-changes`](~/.claude/skills/review-changes/SKILL.md) skill — run it on uncommitted changes before landing a non-trivial PR. The rules below are write-time mnemonics; project-specific ones (Internal/External modules) stay here in full.
16
+
15
17
### Internal vs External Modules
16
18
17
19
We distinguish between **internal modules** (under packages with `_` prefix, e.g. `_internal.*` or `connectors.*._source`) and **external modules** (which users can directly import).
@@ -32,25 +34,14 @@ We distinguish between **internal modules** (under packages with `_` prefix, e.g
32
34
* Standard library and internal imports don't need underscore prefix
33
35
* Only prefix symbols that are truly private to the module itself (e.g. `_context_var` for a module-private ContextVar)
34
36
35
-
### Imports
36
-
37
-
Prefer top-level imports. Only use local (in-function) imports when truly necessary — e.g. to break circular dependencies or to defer a heavy import that isn't always needed.
38
-
39
-
### Type Annotations
40
-
41
-
Avoid `Any` whenever feasible. Use specific types — including concrete types from third-party libraries. Only use `Any` when the type is truly generic and no downstream code needs to downcast it.
42
-
43
-
### Multi-Value Returns
44
-
45
-
For functions returning multiple values, use `NamedTuple` instead of plain tuples. At call sites, access fields by name (`result.can_reuse`) rather than positional unpacking — this prevents misreading fields in the wrong order.
46
-
47
-
### Single Source of Truth
48
-
49
-
When the same value or logic appears in multiple places, consolidate it into one canonical definition. Don't scatter literals, constants, or path construction across files.
50
-
51
-
### Dead Code
37
+
### General principles (also covered by `/review-changes`)
52
38
53
-
When changes make code unreachable or unused, delete it along with its tests. Don't leave orphaned modules around.
39
+
-**Top-level imports.** Defer to in-function only for a real circular dependency or a heavy import that isn't always needed.
40
+
-**Specific types over `Any`.** When a value enters as a weaker form (`str`, `Any`), convert to the strong type at the earliest point. Don't propagate the weak form.
41
+
-**`NamedTuple`/small dataclass for multi-value returns.** Access fields by name at call sites.
42
+
-**Single source of truth.** When the same value or logic appears in multiple places, consolidate it.
43
+
-**Delete dead code and dead config.** When a change makes something unreachable, the code, the tests, and the knobs all go.
44
+
-**Honest names.** The name describes what the code does today.
0 commit comments