House Style#
Every codebase has opinions; Serena writes its down where its agents can read them — as
checked-in memories under
.serena/memories/. This page is
the human rendering of the load-bearing one,
critical_info.md;
where the two disagree, the memory wins.
Design#
The style is idiomatic, object-oriented Python — Java-esque principles, Pythonic syntax:
Each concern has exactly one home. A mechanism whose parts are only correct in combination is implemented as one class, and its parts are private to it. Helpers and constants used by a single abstraction live inside it, not beside it.
Invariants are enforced through structure and visibility. An interface should not permit states the design forbids.
Non-trivial interfaces take explicitly typed abstractions, not bare functions — the strategy pattern rather than a callback parameter.
Dataclasses over dictionaries and tuples for anything that stores structured data.
Testing#
Test only externally observable behaviour, never implementation structure. The litmus test: a behaviour-preserving refactoring must not break any test — a test that could break is wrong and must not be written.
When functionality is removed, its tests are deleted. There are no tests asserting the absence of something: absence of an implementation detail is not a behaviour, and such tests only freeze the current implementation.
Fewer, behaviour-anchored tests are preferred; a missing test is better than an implementation-coupled one.
Language-server tests are marker-gated per language, and snapshot tests use syrupy — see Getting Started for how tests are selected and skipped.
Docstrings and comments#
reStructuredText, consistently —
:param x:,:return:.A tool’s docstring is its prompt. For every
Toolsubclass, what the docstring says is exactly what the LLM reads: editing one changes the agent’s behaviour, not just the documentation. The machinery behind this is in serena.tools.tools_base.Function bodies are structured into functional blocks separated by blank lines, each headed by a concise, lower-case elliptical phrase describing what the block is for.
Each piece of information appears exactly once, at the element that owns it: callers do not explain callees’ internals, and callees do not describe their callers.
Mechanics#
The formatter and linter is ruff (line length 140, double quotes, docstring code formatting on);
the type checker is ty. None of this needs remembering:
uv run poe format and uv run poe type-check apply it, and CI holds
the same line.
When in doubt, open a neighbouring file: the codebase is consistent enough to teach by example, and review will nudge you the rest of the way.