Skip to content

Harness adapter abstraction

Apothem uses a single shared profile (the source tree under src/apothem/, plus the root CLAUDE.md and settings*.json) as the source of truth and derives every harness-specific config from it via adapter classes that implement the HarnessAdapter protocol. Each adapter writes into its harness's native configuration directory — for example, the Claude Code adapter materializes into ~/.claude/.

Protocol definition

from abc import ABC, abstractmethod
from pathlib import Path

class HarnessAdapter(ABC):
    name: str                    # adapter identifier (e.g. "cursor")
    display_name: str            # display label (e.g. "Cursor")

    @abstractmethod
    def install(self, profile: Path, scope: str = "user") -> None:
        """Derive and write native config from the shared profile."""

    @abstractmethod
    def verify(self, profile: Path) -> list[str]:
        """Return a list of verification failure messages (empty = pass)."""

    @abstractmethod
    def uninstall(self, scope: str = "user") -> None:
        """Remove native config files written by this adapter."""

    def update(self, profile: Path, scope: str = "user") -> None:
        """Default: re-run install. Override for incremental update logic."""
        self.install(profile, scope)

Entry-point registration

Adapters register via the apothem.harnesses setuptools entry-point group:

# In the adapter package's pyproject.toml
[project.entry-points."apothem.harnesses"]
cursor = "apothem_cursor.adapter:CursorAdapter"

Apothem discovers all registered adapters at runtime:

import importlib.metadata
adapters = {
    ep.name: ep.load()()
    for ep in importlib.metadata.entry_points(group="apothem.harnesses")
}

Profile-to-native mapping

Each adapter implements the translation logic appropriate to its harness:

Shared profile surface        Harness-native surface
---------------------         ----------------------
CLAUDE.md                -->  GEMINI.md / AGENTS.md / copilot-instructions.md
src/apothem/rules/      -->  .cursor/rules/*.mdc / .windsurfrules
settings.json hooks      -->  harness extension hooks (where supported)
src/apothem/agents/     -->  harness agent definitions (where supported)

Adding a new adapter

See Authoring a harness adapter for a step-by-step guide.