Install
$ agentstack add skill-furedea-agent-harness-python-style ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Python Coding Style Guidelines
Scope
This skill governs code written inside an already-bootstrapped Python project — class design, test authoring, refactoring, code review, naming, imports, docstrings.
Project bootstrap (flake.nix, direnv, uv init, initial pyproject.toml merge) belongs to the nix-dev-init skill. If the project is not yet bootstrapped, defer to nix-dev-init first and return here once direnv allow succeeds and the shell has uv on PATH.
Why the split
Keeping bootstrap out of this skill has two benefits: (1) when Claude is triggered to write or refactor Python code in an existing project, it does not read a long bootstrap procedure it does not need; (2) the nix flake.nix → direnv → uv init → pyproject.toml ordering is an invariant owned by nix-dev-init — duplicating a shortcut here would let it drift.
Package Management
- Use only
uvfor package management, don't usepip - Install dependencies using
uv sync - Run tools using
uv run {tool} - Baseline tooling dependencies belong in template-defined dependency groups, not ad hoc commands
- Add project-specific dependencies using
uv add {package} - Add project-specific tool dependencies using
uv add --group {package} - Upgrade pinned packages using
uv lock --upgrade-package {package} - Prohibited:
uv pip install,uv add --dev,@latest
Directory Structure
- Store production code including entry points in
./srcdirectory - Store test code in
./testsdirectory - For an application or internal project, prefer flat module placement like
src/main.py - Use
src//only when the project is explicitly a distributable package or library with a real package namespace - If a tool or template generates
src//by default, do not keep it unless the project actually needs package semantics
File Standards
- Keep code within 119 characters per line (URLs may exceed this limit)
- Always include type hints
- Use ty for static type checking
Static Type Checking
- ty should already be provided by the project's
typecheckdependency group - Run type checks using
uv run ty check - Check specific paths using
uv run ty check src tests - Use
uv run ty serveronly for editor or language-server integration - Do not introduce another type checker unless the existing project is already standardized on it
Testing
- Use only
pytestas test framework, do not useunittest - Run tests using
uv run --frozen pytest - Use
anyiofor async tests, do not useasyncio - Use
pytest-mockfor mocking (mockerfixture), do not useunittest.mockdirectly pytest,anyio, andpytest-mockbelong in the template's test dependency group- Test coverage should include edge cases and errors
- Always add tests for new features
- Add unit tests for bug fixes
Test Structure
- Function-based by default; class only for namespace grouping or
setup_method/teardown_method @pytest.fixture: shared setup across 2+ tests, external resources, or teardown viayield; put inconftest.pywhen shared across files- Helper function: prefer over fixture when arguments need to be passed or setup is lightweight
@pytest.mark.parametrize: same logic with different inputs- Fixture scope: default
function; usemodule/sessiononly when setup is expensive - Mocking: use
mocker.patch("mod.func", autospec=True)— enforces real signature, catches wrong-argument bugs silently missed by plain mocks
Async test pattern:
# conftest.py
import pytest
@pytest.fixture
def anyio_backend() -> str:
return "asyncio"
# tests/test_xxx.py
import pytest
@pytest.mark.anyio
async def test_something() -> None:
result = await some_async_func()
assert result == expected
Syntax Rules
Classes
- In Python modules, prefer
Enum -> model/class -> functionordering when those concepts coexist - Use
__slots__to restrict variables when not usingdataclassesorpydantic
class Foo:
__slots__ = ("name", "age")
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
- Value Objects:
- When
pydanticis a project dependency: usepydantic.BaseModel(see [Pydantic](#pydantic) section) - When
pydanticis not a dependency: usedataclasses.dataclass(frozen=True, slots=True)—slots=True(3.10+) auto-generates__slots__, no need to write it manually - When difficult to determine, defer judgment to user
- Use
__post_init__to enforce invariants:
@dataclass(frozen=True, slots=True)
class Age:
value: int
def __post_init__(self) -> None:
if self.value Self: # pure → classmethod
return cls(instance_id=data["id"], repo=data["repo"])
def load_instance(instance_id: str) -> SWEInstance: # I/O → module-level function
row = fetch_from_dataset(instance_id)
return SWEInstance.from_dict(row)
# WRONG — module-level factory for pure construction:
def swe_instance_from_dict(data: dict) -> SWEInstance: ... # move inside as classmethod
Pydantic
Frozen model config: pydantic.ConfigDict(extra="forbid", frozen=True, strict=True, validate_default=True)
When multiple frozen models exist, extract a shared base class to base.py:
import pydantic
class FrozenModel(pydantic.BaseModel):
model_config = pydantic.ConfigDict(extra="forbid", frozen=True, strict=True, validate_default=True)
Enums
- Use
Enum/StrEnumfor fixed choices instead of raw string literals or dict maps - Convert user input strings to Enum early, then map through Enum values
- Prefer
StrEnumwhen values are serialized or user-facing
Functions
- Keep functions focused and small
- Use Pythonic syntax (comprehensions,
withstatements, etc.) - Don't use
global,nonlocal(not explicit enough) - Use built-in generics (e.g.,
tuple,list,dict) instead oftyping.Tuple,typing.List,typing.Dict
Strings
Quote Usage
- String contains
'→ use" - String contains
"→ use' - f-strings (variable substitution) → use
" raisestatements → use"(normal sentences use')
Operators
- Separate operators and operands by one space
- When using 2+ operators, omit spaces around
*,/,//,%,**(higher precedence)
Logging
Write in dictionary format. Add extensive logging at critical system points where failures would be hard to diagnose (CSV file references, before/after raise statements, etc.).
logger.info({"action": "save", "csv_file": self.csv_file, "status": "run"})
Naming Conventions
- Constants:
SCREAMING_SNAKE_CASE— define semantically meaningful string literals as module-level constants (two blank lines after imports) rather than embedding them inline - Variables / functions / files:
snake_case - Getters: name of the output variable
- Classes:
UpperCamelCase - Iterator arguments:
- Loop body ≤ 2 lines: single character (
x,i) - Loop body ≥ 3 lines: descriptive name
File Naming
- Name files after the domain/action they represent, not the role suffix
- Prefer
retrieval.pyoverretriever.py,prompt.pyoverprompt_builder.py -er/-orsuffixes belong on class names (e.g.class Retriever), not file names- Avoid
utils.py/helpers.py— name by what the module actually does (e.g.model.py,inference.py)
Whitespace & Layout
Two blank lines before/after
- Import statements
- Global variable definitions
- Object (class/function) definitions
One blank line between
- Function/method docstring sections: summary
""", detail,Args,Returns/Yields,Raises - Import groups (standard / third-party / local / personal)
- Instance methods
Imports
- Order import groups as: standard library → third-party → local
- Use exactly one blank line between these groups
- Avoid
from ... import ...unless the imported name is self-explanatory (e.g.,Enum,Path), or the module path is so long thatmodule.nameat call sites becomes unwieldy (e.g.,from swebench.inference.make_datasets.utils import extract_diff) - Avoid
asaliases unless required for clarity
Indentation
- When handling multiple objects in parallel, align indentation with the previous element
Line Breaks
- One element per line for lists/dicts with 3+ items or long expressions; trailing comma on last element
- Don't sacrifice readability for brevity
# Good
sections = [
problem_statement,
*_file_sections(files),
"Please output a unified diff patch.",
]
# Bad
sections = [problem_statement, *_file_sections(files), "Please output a unified diff patch."]
Comments & Docstrings
- Write comments on their own line above the relevant code
- Always add docstrings to public APIs
- Comment non-obvious choices (algorithm params, fallback behavior, encoding handling)
# File level
"""Explanation of file functionality"""
# Class & method level
class MyClass:
"""Class functionality explanation"""
def method(self):
"""Method functionality explanation"""
# Function level
def function_name(arg1, arg2):
"""Function functionality summary.
(Detailed function functionality.)
Args:
arg1 (type): Argument description
arg2 (type): Argument description
Returns/Yields:
type: Return value description
Raises:
ErrorType: Error description
(see details at: URL)
"""
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: furedea
- Source: furedea/agent-harness
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.