Skip to main content

farrier

PyPI

farrier renders an agent-neutral prompt library into a repository — generating the skill, prompt and instruction adapters expected by Codex, Claude, and GitHub Copilot, plus the launcher scaffolding (.agents/agents.mk and friends) that keeps those adapters current.

A farrier is the craftsman who fits the right gear onto each horse. This tool fits the shared prompt library onto each repository.

Install

pipx install farrier        # or: uv tool install farrier

The farrier package ships no library content of its own. Content resolves across two layers: the base library — plain data, the toolchain skills and the packs that select them, with nothing to install or import — and an optional private overlay that shadows it name-for-name. Point farrier at an overlay once:

farrier config set-library /path/to/the/overlay
farrier config show

config writes one shared TOML file, ~/.config/stablemate/config.toml (~/Library/Application Support/stablemate/ on macOS, %APPDATA%\stablemate\ on Windows; $STABLEMATE_CONFIG overrides it). Every stablemate tool reads and writes that same file, so library_dir and base_dir mean one thing across all of them — a pre-existing ~/.config/farrier/config.toml is still read, and folded in on the first write.

Finding the base library. farrier discovers the base via, in order, $STABLEMATE_BASE_DIR → the base_dir config key (farrier config set-base <path>) → a configured stablemate_dir checkout (<checkout>/base-library) → the shared cache at ~/.cache/stablemate. The cache is deliberately last, so a fetched copy can never shadow a checkout you are editing.

farrier install fetches the base, and updates it. It is the only command that touches the cache, so under pipx — where each tool is its own venv and the base is data with no package to import — you get a working base library without configuring anything. An update asks the remote for the head of main first, so an already-current cache costs one round-trip rather than a re-clone. Three qualifications:

  • A base you named is never fetched over. If $STABLEMATE_BASE_DIR, set-base or a stablemate_dir checkout answers, install returns it without even probing the remote.
  • --check fetches but never updates. It writes nothing and runs in CI, where a library moving underneath the comparison would make the result depend on the hour.
  • Failure keeps what works. Offline, STABLEMATE_FETCH_BASE=0, or a broken clone all leave the existing cache in place rather than leaving you with none.

STABLEMATE_FETCH_BASE=0 forbids the network entirely; STABLEMATE_CACHE_DIR relocates the cache. See the monorepo README for the full resolution order and why everything other than install reads the cache frozen.

Use

In a repository that has no agents.yml yet:

farrier init                # write a starter agents.yml (--force to replace one)

init reads nothing — no library, no config — so it works on a fresh machine before farrier config set-library. It refuses to overwrite an existing agents.yml.

Then, from a repository that has one:

farrier --repo .            # render/install the selected packs
farrier --repo . --check    # verify generated files are up to date (no writes)

Rendering is the default action; farrier install --repo . is an accepted alias of farrier --repo .. A bare farrier with no arguments prints the verb listing.

The rest of the verbs:

farrier config show                        # every config key as key=value
farrier source .claude/skills/x/SKILL.md   # the library file that generated an adapter
farrier scaffold --list                    # the scaffolds this repo may apply, and their params
farrier scaffold <id> [--param KEY=VALUE]  # seed repo files from one
farrier workflows                          # the workflows installed on this machine
farrier version

source takes the path of a generated file and prints the library file behind it. It is the one to reach for before editing anything under .claude/, .codex/ or .github/: those are outputs, and an edit there is discarded by the next install.

Configuring agents.yml

agents.yml (at your repo root) selects what farrier renders. farrier init writes a starter one with the common keys as commented examples. Every option — repo, agents, packs, skills/prompts/roots, scaffolds, exclude, localInstructions, template/vars, and workflow — is documented with inline comments in agents.example.yml. Copy it to your repo as agents.yml and prune to taste.

Library layout

The other side of the contract is the agent library farrier renders from — what goes in library/skills/, library/prompts/, packs/ and scaffolds/, the file formats expected, and how source names map to generated adapters. That is documented in docs/LAYOUT.md.

A skill or prompt is markdown with YAML frontmatter, and farrier.frontmatter reads it with a markdown parser and yaml.safe_load — never a fence regex. (It is farrier's own module rather than ostler.markdown because farrier needs frontmatter only and does not depend on ostler; both follow the same rule, which the stablemate-structured-parsing skill states in full.) A CRLF file, a closing --- with a trailing space and a file with no newline after it are all ordinary documents, and the regexes that preceded this read every one of them as having no frontmatter at all.

Farrier does not install workflows. A library ships none, agents.yml has no workflows: key, and nothing is written to .agents/workflows/. A workflow is a Python distribution that brings its own command: install it with pip/uv and run it directly.

uv tool install workhorse-workflows
workhorse-coder run --dry-run    # static preflight, drives nothing
workhorse-coder run

Locating the library

--library DIR, $FARRIER_LIBRARY_DIR and library_dir in the home config (farrier config set-library) select the overlay, in that precedence. The base library is found separately, by the order under Install above, and the two stack: the overlay first, then the base.

A directory counts as a library if it holds library/ — that is the whole contract. Point farrier at one that does not and it exits with a setup hint; configure no overlay at all and it runs base-only, which is a supported setup rather than an error. Only with neither an overlay nor a base does it refuse to start.

Related

  • workhorse-agent — the fail-soft runner that executes the workflows, against the adapters farrier renders.
  • ostler — the doc-graph CLI those workflows shell out to.

All three live in the stablemate workspace.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

farrier-2.1.0.tar.gz (82.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

farrier-2.1.0-py3-none-any.whl (86.7 kB view details)

Uploaded Python 3

File details

Details for the file farrier-2.1.0.tar.gz.

File metadata

  • Download URL: farrier-2.1.0.tar.gz
  • Upload date:
  • Size: 82.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for farrier-2.1.0.tar.gz
Algorithm Hash digest
SHA256 6570c91d687c83e7d72126f810d988b0c878d7f92f385e7c15b60029be1de04e
MD5 41ab12c5c5d540ae2e0c3fde433f960f
BLAKE2b-256 1ee16ac818da257289e6884b7e3b43f45e98e58661c0af17af8333020d45ed86

See more details on using hashes here.

Provenance

The following attestation bundles were made for farrier-2.1.0.tar.gz:

Publisher: release.yml on GabrielCpp/stablemate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file farrier-2.1.0-py3-none-any.whl.

File metadata

  • Download URL: farrier-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 86.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for farrier-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5761ff7049932275c1b295b3b546d6157b36028cabf6bbdbbb94feb869ed32a6
MD5 e84dc8d083f5240f754b0563415f5b27
BLAKE2b-256 3591b5866b3f49a8ad8015bad17d919359c0329f4ce07a597ee6f0a8f03d8c4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for farrier-2.1.0-py3-none-any.whl:

Publisher: release.yml on GabrielCpp/stablemate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page