agentleFS
sovanticasovantica/engrava-mcp/CLAUDE.md

engrava-mcp

CLAUDE.md1 starsChanged 52 days agoMITView on GitHub

This is a public repository (engrava-mcp) — Model Context Protocol server exposing Engrava as agent memory. Assume every commit message, PR title, PR body, branch name, code comment, and docstring is world-visible. Public-safe by default. This is production code maintained to a high quality bar. A feature is not "done" until every point below holds: - Layout: mirror the source tree under tests/ (e.g. tests/domain/, tests/infrastructure/). - A test's level is defined by what it touches, not by its size…

  • Installs packages

The file

We split this CLAUDE.md into the rules it gives an agent

6 rules. About 0 are common, 5 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    Prefer protocol-based fakes over mocks.

    line 68
  2. Distinctive:

    Run a clean test suite locally before pushing.

    line 70
  3. Distinctive:

    Never leak infrastructure types (HTTP clients, SDK objects, raw rows) into the domain.

    line 80
  4. Distinctive:

    No internal metrics or thresholds: Never quote internal gate floors, coverage numbers, benchmark scores, or private tooling names in a …

    line 113
  5. Distinctive:

    If you find yourself writing a second sentence to justify the first, the detail belongs in the PR description or the linked issue — not the …

    line 117
  6. Very specific:

    Read CONTRIBUTING.md for the contribution flow.

    line 137

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md
<!-- Generated by 0.1.0 (2026-09-01T21:02:53Z) from a shared template — do not edit directly. -->

CLAUDE.md — engrava-mcp

This is a public repository (engrava-mcp) — Model Context Protocol server exposing Engrava as agent memory.

Assume every commit message, PR title, PR body, branch name, code comment, and docstring is world-visible. Public-safe by default.

Context

AspectValue
LicenseMIT
Primary languagepython 3.11+
Default branch for PRsthe active release/vX.Y.Z branch
Release flowManual version in pyproject.toml and server.json + maintainer-created vX.Y.Z tag on main
Contribution modelissues + PRs on GitHub

Repository-specific rules

  • Thin MCP server: consume Engrava's public API only — no internals access.
  • Transport: stdio; the surface is MCP tools / resources / prompts.
  • Store resolution via env vars (ENGRAVA_MCP_CONFIG, ENGRAVA_DB_PATH, ENGRAVA_MCP_READ_ONLY).
  • Quality gate: ruff ALL + mypy strict + 90% test coverage.

Code quality — zero-compromise bar

This is production code maintained to a high quality bar. A feature is not "done" until every point below holds:

  • Linting — ruff check clean, ruff format --check clean, no rule disables without a justifying comment.
  • Typing — mypy --strict clean. No bare Any. No # type: ignore without a justifying inline comment.
  • Coverage — 90% minimum, enforced by --cov-fail-under=90. TDD preferred; tests are first-class code.
  • Docstrings — Google-style on every public symbol (params, returns, raises, examples).
  • Domain modelling — concrete types per concept, no catch-all dicts, no god objects.
  • Errors — typed exceptions; never bare except; never swallow errors silently.
  • No shortcuts — no TODO/FIXME/HACK in production code; open an issue instead. No dead code. No magic strings.
  • Secrets — never hard-code API keys; use env vars or config objects; never log secrets.

Run locally before opening a PR

pip install -e ".[dev]"
ruff check src/ tests/
ruff format --check src/ tests/
mypy --strict src/
pytest --cov --cov-fail-under=90

Testing conventions (python)

  • Layout: mirror the source tree under tests/ (e.g. tests/domain/, tests/infrastructure/).
  • A test's level is defined by what it touches, not by its size or speed:
    • unit — in-process only, I/O confined to tmp_path. Unmarked; this is the default.
    • integration — real local resources (on-disk database, real file layout, a subprocess of this project's own CLI). Marker: integration.
    • external — network, third-party APIs, package indexes. Marker: external; never runs in the default selection, and anything that costs money requires an explicit environment-variable opt-in.
  • Strict marker checking is on: an unregistered marker is an error. Set both --strict-markers in addopts and the strict_markers ini key. Measured 2026-09-01 on one unregistered marker: pytest 8.4.2 honours the flag and ignores the ini key, 9.0.3 does the reverse, 9.1.1 honours both. Neither alone enforced on all three versions, so set both. slow means > 5 s wall clock and is orthogonal to level — a fast integration test carries no slow, a slow unit test does.
  • Error-path tests assert the error type and the state. Use the real exception type (never bare Exception, never a base class where the code raises a subclass) and assert that nothing was written. Assert resulting state before the return value: a return-value assertion placed first aborts there when the behaviour breaks, hiding what actually happened.
  • asyncio_mode = "auto" if async work is involved — async def test_* directly, no decorators.
  • Prefer protocol-based fakes over mocks; never test against live external APIs in CI.
  • Shared fixtures in tests/conftest.py.
  • Run a clean test suite locally before pushing; CI is a check, not a write loop.

Architecture — layered imports (flow downward only)

LayerPathMay import
Domainsrc/<package>/domain/stdlib, value-object libs, parent project's public API only
Infrastructuresrc/<package>/infrastructure/Domain only
Plugin entrysrc/<package>/manifest.py (or equivalent)Domain + Infrastructure

Never leak infrastructure types (HTTP clients, SDK objects, raw rows) into the domain. Cross the parent project's boundary only through its documented public protocols.

Commit messages — Conventional Commits 1.0.0

Format: <type>(<scope>): <description>

TypeWhenVersion impact
featNew user-visible featureminor bump
fixBug fixpatch bump
perfPerformance improvementpatch bump
docsDocumentation onlyno release
refactorRefactor without behaviour changeno release
testTestsno release
build/ci/choreTooling, maintenanceno release

Breaking changes: add ! after type/scope AND a BREAKING CHANGE: footer.

Keep messages terse. The header carries the change; add at most one short line of context. Do not itemize every file or sub-change — the diff is already in git, and detail belongs in the linked issue/PR. For fixes especially: a header like fix: bugfixes or fix(<scope>): assorted fixes is preferred over a list of every bug addressed. Don't write a development diary.

Branch + commit hygiene. Use the public release tag (vX.Y.Z) and this repo's GitHub issue/PR numbers (#N) as your only durable identifiers. Locally-documented ADRs (docs/adr/ADR-NNN-*.md) may be referenced once the corresponding file exists in this repo. Generic feature descriptions and Conventional Commit headers are always welcome.

Before committing, ask: could this commit message, branch name, or referenced symbol reveal information about a workflow that should stay private? If unsure, ask a maintainer. When in doubt, default to omitting the reference.

A commit-message hook (installed locally) provides a quick feedback loop for this check.

CHANGELOG — no filler

A changelog entry is a one-line note to a user about what changed for them. It is not a development diary.

  • One line per entry. Imperative mood, the user-facing effect, no trailing prose. Load sqlite-vec on the connection's worker thread so configuration no longer crashes. — not a paragraph explaining the threading model.
  • The CHANGELOG is hand-maintained (Keep a Changelog format). Each release gets its own section, written by hand as part of preparing that release. Add entries under the appropriate group as you land user-facing changes, and keep each one to a single line — no explanatory paragraphs under an entry.
  • Write for the reader, not the author. State what changed and why it matters to someone using the project — omit the investigation story, the internal reasoning, and any build/CI/benchmark mechanics that are not user-visible.
  • No internal metrics or thresholds. Never quote internal gate floors, coverage numbers, benchmark scores, or private tooling names in a public CHANGELOG. Generic "added a pre-release quality gate" is enough.
  • Keep a Changelog grouping is fine (Added / Fixed / Changed / Deprecated / Removed / Security), but each bullet stays to a single line.
  • Group fixes; don't enumerate them. A release that fixed several small bugs gets one line — Bug fixes and stability improvements. — not a bullet per bug. List a fix individually only when a user specifically needs to know it changed (e.g. a behaviour they relied on). Routine internal fixes roll up.

If you find yourself writing a second sentence to justify the first, the detail belongs in the PR description or the linked issue — not the CHANGELOG.

Branching

This repo follows a three-tier feature/* → release/vX.Y.Z → main flow.

BranchRole
mainStable mirror — the branch users land on when cloning. Updated by forward-merging the active release/vX.Y.Z branch once a version is ready. main never originates a release on its own.
release/v<X.Y.Z>The active integration and stabilisation branch for the next version. Feature branches are squash-merged here; when the version is ready it is forward-merged into main.
<type>/<kebab-description>Feature / fix / chore branches. Plain English; no internal identifiers; ≤ 50 chars.

Open PRs from your feature branch targeting the active release/vX.Y.Z branch; those merge in with a squash. Branch names should describe the change in plain English (feature/priority-signal-hybrid-search, fix/empty-count-on-mindql, docs/quickstart-update).

Releasing is manual: the version is set by hand in pyproject.toml and server.json, the active release/vX.Y.Z branch is forward-merged into main, and a maintainer then creates the matching vX.Y.Z tag on main. That tag is what triggers the publish workflow.

Contributions

External contributions are welcome. Please:

  1. Read CONTRIBUTING.md for the contribution flow.
  2. Open an issue first if the change is non-trivial — it's faster than rework after a PR.
  3. Branch from the active release/vX.Y.Z branch, follow Conventional Commits, run the local quality gate before pushing.
  4. Open a PR targeting the active release/vX.Y.Z branch. CI must be green before review.

Code review uses GitHub PR comments. Discussions for design questions live in GitHub Discussions if enabled.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.