Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add skills/deephaven/deephaven-mcp/ref-python-coding-practicesnpx skills add deephaven/deephaven-mcp --skill ref-python-coding-practicesgit clone --depth 1 https://github.com/deephaven/deephaven-mcpWhat it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00125 | $0.05301 |
| Opus 5 | $0.00063 | $0.02651 |
| Sonnet 5 | $0.00025 | $0.01060 |
| Haiku 4.5 | $0.00013 | $0.00530 |
Grade A, and why
ref-python-coding-practices scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured yesterday.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 98 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Python Coding Practices
- A Python file must not access private variables, functions, or methods in another file or package. It is ok for the test file for a package to access and use the package being tested, even if it is private, and it is ok for the test file to access private variables, functions, and methods in the package.
- All MCP tools (async functions registered via
server.tool()(fn)insideregister_tools(server: FastMCP)) have specific docstring requirements — apply thepydocs-improveskill for the full rules, including required "Terminology Note" and "Format Accuracy for AI Agents" sections. - f-strings are preferred over
%and.format()in format statements. - File moves and renames preserve history — use
git mvandgit rm, never delete-plus-create. Canonical source:AGENTS.mdVersion Control. - A Python file named
<file>.pyshould have a single test file namedtest_<file>.py. An exception is made for integration tests which are namedtest_<file>_integration.py. Both the unit test and the integration test live in the sametests/<package>/directory that mirrors the source's package — not in a separate top-level directory liketests/<package>_integration/. The correct shape istests/test__logging.pyandtests/test__logging_integration.pyas siblings; the wrong shape is a paralleltests/integration/tree.- The mirror root follows the source root.
src/deephaven_mcp/cli/_help.py→tests/cli/test__help.py; the top-levelscripts/convert_config_v1_to_v2.py→tests/scripts/test_convert_config_v1_to_v2.py. A directory that is not a Python package of the shipped library still gets its mirror. test__<name>.py(double underscore) is reserved for mirroring a private module or package named_<name>.tests/cli/test__daemon_integration.pyis correct becausecli/_daemon/exists. Applying that form to theconfigintegration test would have been wrong — there is nocli/_configmodule or package — which is why it lives attests/cli/_commands/test_config_integration.py, mirroringcli/_commands/config.py. Using the double-underscore form for anything else advertises a source file that was never written, the single most common way test layout drifts.- A test whose subject is broader than one source file — a guardrail/contract test, or a package-scope integration test — is named for its subject or invariant (never for a module it does not mirror) and lives in the directory mirroring the narrowest scope containing everything it validates. A guardrail test also carries
@pytest.mark.guardrail, so the project's convention-enforcement suite is selectable withuv run pytest -m guardrail. Guardrails are deliberately not collected into one directory: each sits with the code it guards, and the marker — not a shared path — is what makes the family selectable.- Scope means the declarations a guardrail audits, not every package it imports. A drift check reads one side's declarations and compares them against the other side as reference data; it belongs with the declaring side.
tests/cli/test_tool_wrapper_drift.pyimports from bothcli/andmcp_systems_server/_tools/, but thewraps_tooldeclarations it audits exist only incli/, so it lives intests/cli/rather than at thetests/root. - Canonical implementations:
tests/test_field_docs_contract.py(walks the whole package, so thetests/root is the only scope wide enough),tests/cli/test_help_contract.py(every command's help satisfies the help contract),tests/cli/test_tool_wrapper_drift.py(every CLI wrapper matches its MCP tool),tests/agents/test_skills_catalog.py(mirrors.agents/, not asrc/package at all),tests/mcp_systems_server/_tools/test_tool_module_inventory.py(the tool-module set matches its documented inventory).
- Scope means the declarations a guardrail audits, not every package it imports. A drift check reads one side's declarations and compares them against the other side as reference data; it belongs with the declaring side.
- The mirror root follows the source root.
- Prefer specific type hints over
Any. UsingAnyrequires an inline justification comment naming the external constraint (third-party stub gap, dynamic plugin interface) that forces it. Without the comment, mypy and reviewers cannot distinguish a deliberateAnyfrom a lazy one. - Do not use
hasattrorgetattrfor type narrowing or feature detection. They silently maskAttributeErrors and bypass mypy. Preferisinstance, structural typing (typing.Protocol), or restructuring the API so the attribute is always present. Whengetattris genuinely required (reflection over a closed set of names), pair it with an inline comment naming the constraint. - Use American English spelling throughout all code, comments, docstrings, and documentation. For example: "initialized" not "initialised", "recognized" not "recognised", "color" not "colour". Mechanically enforced by
uv run codespell(part of./bin/precommit.sh) using the en-GB-to-en-US dictionary; silence an intentional non-American form (e.g. a quoted counterexample) with an inlinecodespell:ignorecomment on the same line, followed by the comma-separated words to ignore. - Unused function parameters should be indicated by prefixing the parameter name with a single underscore (e.g.,
_request,_host,*_args,**_kwargs). This is the conventionruff/pyright/pylintrecognize out of the box and derives from PEP 8's throwaway-variable convention. Do not usedel paramat the top of a function body to silence unused-argument warnings. The leading-underscore prefix is preferred overdel paramfor all new code.- Exception: when callers of the function pass the argument by keyword (and changing the public name would be a breaking change), keep the original name. In that case, either suppress the lint warning locally or use
*_args/**_kwargsfor generic stubs. - Framework/dispatcher-driven handlers (Starlette route handlers, protocol-dispatch callbacks in
_run_server, etc.) receive their arguments positionally — the framework does not pass them by keyword name — so the previous exception does not apply and you should use the_prefix on unused parameters there.
- Exception: when callers of the function pass the argument by keyword (and changing the public name would be a breaking change), keep the original name. In that case, either suppress the lint warning locally or use
- In tests, use
AsyncMockfor async functions/coroutines andMagicMockfor synchronous ones. UsingMagicMockwhereAsyncMockis needed is a common mistake — it causes tests to pass or fail misleadingly because the mock does not properly handleawait. - Do not use
assertfor invariants or defensive checks in production code undersrc/. Python's-Oflag strips assertions, and the project's lint config (ruffruleS101) flags them — adding# noqa: S101to bypass that rule is not acceptable. For internal invariant violations, raisedeephaven_mcp._exceptions.InternalError(or a more specific subclass) with a descriptive message. Every defensive raise must have a unit test that triggers it — if the path is "unreachable in normal use," construct the test fixture that proves the guard fires when bypassed.assertis fine in test files (tests/) where it is the standard expression of test expectations. - Docstrings describe what the function, method, class, value, module, or package is and does — never why it exists. Design rationale, API-symmetry justifications, cross-call-site narratives, and meta-commentary about how the code fits with other code belong in commit messages, PR descriptions, or — when truly load-bearing — a brief comment near the relevant line. Deletion test: if a docstring's body would not make sense to a caller trying to use the function (it explains the author's reasoning rather than the contract), delete that body.
- Contract-level details are part of the what. Details that affect how a caller uses the function (e.g., "returns
Nonewhen X so the caller can skip the retry") belong in the docstring. - Constants and getters stay minimal. A constant's docstring is one line stating what the value represents. A getter that reads a config key describes the key it reads and the fallback — it does not narrate the larger API's design.
- Package
__init__.pydocstrings are the most-violated case. Apply thepydocs-improve"Module and package docstrings" section for the required shape. - MCP tool docstrings under rule 2 are a deliberate exception — their extra sections are part of the contract for AI-agent callers.
- Contract-level details are part of the what. Details that affect how a caller uses the function (e.g., "returns
- Configuration tunables live in the JSON configuration tree as Pydantic-validated fields, not as ad-hoc
os.environreads or asDEFAULT_FOOconstants. The only configuration-location environment variable the server itself reads isDH_AI_DATA_DIR; the log level comes fromPYTHONLOGLEVELviasetup_logging()(docs/ENV.mdis the canonical inventory). Apply theref-configuration-conventionsskill before adding a new tunable, refactoring a config model, or wiring an environment variable into the code. - Every field on a field-bearing value class — a Pydantic
StrictSchema/RedactableSchemasubclass, a@dataclass, or atyping.NamedTuple— carries a PEP 257 trailing docstring, never a class-levelAttributes:block. Trailing docstrings sit next to the field, survive refactors, and (for Pydantic) reach runtime consumers (model_fields[name].description,model_json_schema(), MCP tool schemas) that anAttributes:block does not; explicitField(description="...")works but violates project style. The Pydantic subset is enforced bytests/test_field_docs_contract.py;@dataclassandNamedTupleare convention. Canonical implementations:cli/_runtime.py(Runtime, a dataclass),cli/_help.py(OutputField,OutputSpec); apply theref-configuration-conventionsskill for the Pydantic rule and examples.- Plain enums follow the same rule. A plain
enum.StrEnum/enum.IntEnum/enum.Enummember carries a PEP 257 trailing docstring next to its value, never a class-levelMembers:/Values:block. Canonical implementations:SignalOutcome(_processes.py),DaemonState(cli/_commands/daemon.py),InitializationPhase(resource_manager/_registry.py),SystemType/SessionOrigin(_taxonomy.py),ResourceLivenessStatus(resource_manager/_manager.py). - Carve-out: metadata-bearing enums that bind per-member attributes via
__new__. When an enum stores per-member metadata (help text, exit codes, structured payload) by overriding__new__and constructing each member with positional metadata args, the metadata strings are the documentation and trailing docstrings would be redundant. Canonical implementations:ExitCode,ErrorCode(cli/_errors.py). This is the only exception to the per-member-docstring rule for enums.
- Plain enums follow the same rule. A plain
dhcliCLI isclick+@run_async+CliError. Click commands live undersrc/deephaven_mcp/cli/_commands/*.py;argparseis not used. Async callbacks must be wrapped with@run_asyncfromcli/_async.py— never callasyncio.runinline. User-facing failures mustraise CliError(message, code=ErrorCode.X)fromcli/_errors.py— neverprint(..., file=sys.stderr); return 2. Apply thecli-command-addskill when adding or renaming a CLI command.- Surfaced help is plain text, governed by
ref-cli-help-standards, not pydocs. CommandHelpSpecstrings (rendered bybuild_help), everyclick.option(help=...), group docstrings used as help, andErrorCode.help_textare rendered verbatim by click and surfaced in the agents manifest, so they carry no reStructuredText markup (no``, no:func:/:class:). This is the inverse of rule 12, which governs internal (non-surfaced) docstrings — those keep the RST convention. Applycli-help-improve/cli-help-accuracyto the surfaced strings.
- Surfaced help is plain text, governed by
- Python version floor. The supported Python floor is authoritative in
pyproject.tomlunderrequires-python. Rungrep requires-python pyproject.tomlbefore using version-gated syntax — PEP 695 generics (def f[T](...)),tomllib,typing.override,StrEnum, etc. — and re-check whenever you introduce a feature that landed in a recent Python release. Do not duplicate the version number elsewhere in code, docs, or skills; letpyproject.tomlbe the single source of truth. - Named domain exceptions live in
src/deephaven_mcp/_exceptions.py. Inline definitions in the raising module are forbidden — the exceptions module is the single source of truth for the project exception hierarchy.- Inheritance: every named exception inherits — directly or transitively — from
McpError, so unified handling (catch-all middleware, structured logging, the CLI'sCliErrormapping) sees it. - Organization: file is sectioned by domain (
# Session Exceptions,# Configuration Exceptions,# Daemon Registry Exceptions, …). New domains add a base class plus specific subclasses, mirroringSessionError→SessionCreationErrorandDaemonRegistryError→RegistryCorruptError. - Exports: every new name appears in
_exceptions.__all__and in the equality check intests/test__exceptions.py::test_all_exceptions_exported— that test is the enforcement mechanism. The raising module imports from_exceptions; the package__init__.pymay re-export for ergonomic call sites. - Carve-out: plain
RuntimeError/ValueErrorsubclasses are reserved for genuinely-internal helpers that callers never name.
- Inheritance: every named exception inherits — directly or transitively — from
- Closed-set dispatches must be statically exhaustive. When code dispatches on a value drawn from a closed set — a
Literal, anEnum, or a tuple of accepted values — every member must have an explicit case and the fallthrough must calltyping.assert_never(value). Adding a new member must surface as a mypy error in every consumer until each branch is written.- Canonical
matchform:
- Canonical
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- yesterday First seen · 98 lines · 125 tokens per session scan A 2baf7241f794
ref-python-coding-practices is a skill published in the GitHub repository deephaven/deephaven-mcp (5 stars, last pushed 4d ago), licensed Apache-2.0. It adds 125 tokens to every session and 5,301 once invoked, about $0.0006 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other skills, from other repositories
systematic-debugging
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes.
next-cache-components-adoption
Turn on Cache Components in a Next.js app and resolve the blocking routes it surfaces. Use when the user wants to enable, adopt, or migrate to Cache Components, flip the cacheComponents flag, work through a flood of blocking-prerender / instant validation errors, run the cache-components-instant-false codemod, or…
babysit-pr
Babysit a GitHub pull request after creation by continuously polling review comments, CI checks/workflow runs, and mergeability state until the PR is merged/closed or user help is required. Diagnose failures, retry likely flaky failures up to 3 times, auto-fix/push branch-related issues when appropriate, and keep…
imagegen
Generate or edit raster images when the task benefits from AI-created bitmap visuals such as photos, illustrations, textures, sprites, mockups, or transparent-background cutouts. Use when Codex should create a brand-new image, transform an existing image, or derive visual variants from references, and the output…
cpu-profile-analysis
Analyze V8/Chrome CPU profiles (.cpuprofile) and DevTools trace files (Trace-.json). Use when: profiling performance, investigating slow functions, comparing code paths, finding bottlenecks, analyzing timeToRequest, understanding call trees from sampling profiler data, analyzing layout/paint/rendering, investigating…
next-cache-components-optimizer
Drive a Next.js route to instant navigation by setting up an agentic loop, under Cache Components / PPR, on initial load (hard navigation) and client-side navigation (soft navigation). Encode the goal as a failing @next/playwright instant() e2e and work it to green, one verified route at a time; the shipped test then…