Render an agent-neutral prompt library into a repository's Codex/Claude/Copilot adapters.
Project description
farrier
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 env-var and set-base routes are the ones that matter under
pipx, which isolates each tool in its own venv: the base is data with no package to
import, so it can only be found by path. The cache is deliberately last, so a fetched
copy can never shadow a checkout you are editing — though today nothing populates it on
your behalf: farrier._vendor.stablemate_core.base_cache implements the fetch, but no command calls it
yet, so in practice one of the first three routes is what makes a base reachable. See the
monorepo README for how the tools
are installed.
Use
From a repository that has an agents.yml:
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 ..
Four more verbs round it out:
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 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. 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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file farrier-1.5.2.tar.gz.
File metadata
- Download URL: farrier-1.5.2.tar.gz
- Upload date:
- Size: 60.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ebf557e4b2ca936ecb74ae36ba8234a13ff6ab96c42321e82389f60b28102428
|
|
| MD5 |
3a156c2abe8f1d8fb9f70b9b43d7d803
|
|
| BLAKE2b-256 |
9ef011a36e70c90c794146f4fb7a331d2448e23a2864eae3bbaf39e4f24af4b7
|
Provenance
The following attestation bundles were made for farrier-1.5.2.tar.gz:
Publisher:
release.yml on GabrielCpp/stablemate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
farrier-1.5.2.tar.gz -
Subject digest:
ebf557e4b2ca936ecb74ae36ba8234a13ff6ab96c42321e82389f60b28102428 - Sigstore transparency entry: 2332112304
- Sigstore integration time:
-
Permalink:
GabrielCpp/stablemate@a912fc7217b4cdc57c0b71e989b55d876aa1a12c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/GabrielCpp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a912fc7217b4cdc57c0b71e989b55d876aa1a12c -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file farrier-1.5.2-py3-none-any.whl.
File metadata
- Download URL: farrier-1.5.2-py3-none-any.whl
- Upload date:
- Size: 63.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20077fc374438d67819fe1985fd590e14009f0c39a52a52137bc6a8d659caef7
|
|
| MD5 |
66e483b90ad4edcbfcdc35bc260bbb97
|
|
| BLAKE2b-256 |
b3f8008226502c0a359bb3c63c4e5d261d84e29ffc5fbb3268e80eba5e44c167
|
Provenance
The following attestation bundles were made for farrier-1.5.2-py3-none-any.whl:
Publisher:
release.yml on GabrielCpp/stablemate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
farrier-1.5.2-py3-none-any.whl -
Subject digest:
20077fc374438d67819fe1985fd590e14009f0c39a52a52137bc6a8d659caef7 - Sigstore transparency entry: 2332112408
- Sigstore integration time:
-
Permalink:
GabrielCpp/stablemate@a912fc7217b4cdc57c0b71e989b55d876aa1a12c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/GabrielCpp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a912fc7217b4cdc57c0b71e989b55d876aa1a12c -
Trigger Event:
workflow_dispatch
-
Statement type: