Build Your Own Rules: define code checks (ast-grep rules, linters, type checkers, scripts) once, and have your terminal, editor, and AI agents enforce them
Project description
Your AI agent keeps breaking rules you have already given it. You say arguments
past the first couple should be keyword-only; it agrees and listens, but then
later in the session it writes create_user(name, email, True, False, None). So
you add a line to your ever-growing AGENTS.md in the hope it fixes it. It doesn't.
byoris the sheepdog for your flock of coding agents: you set the rules and it reins in any agent that attempts to stray in real time.
byor can do this reliably because the rules it creates are real executable checks,
not markdown prompts. You rarely write one of these rules by hand. If you tell your
agent to create a rule, or even give it critical feedback about code it has written,
it will use byor's skill to create the best automated system to keep your agent in
check. Here is an example:
# .byor/rules/project/keyword-only-args.yml
id: keyword-only-args
language: python
severity: warning
message: Arguments after the first two must be keyword-only. Add `*` so callers pass them by name.
rule:
kind: parameters
any:
- all: # a function whose third argument is still positional
- has: { nthChild: 3, any: [{kind: identifier}, {kind: typed_parameter}, {kind: default_parameter}, {kind: typed_default_parameter}] }
- not: { has: { nthChild: 1, regex: "^(self|cls)$" } }
- all: # a method, where self/cls shifts the limit to the fourth slot
- has: { nthChild: 1, regex: "^(self|cls)$" }
- has: { nthChild: 4, any: [{kind: identifier}, {kind: typed_parameter}, {kind: default_parameter}, {kind: typed_default_parameter}] }
metadata:
byor:
agent_prompt: >
Put a bare `*` after the second parameter so the rest are keyword-only,
e.g. def f(a, b, *, c, d), and pass them by name at the call sites.
A rule like this is a structural ast-grep check,
and byor is set up so this naturally just works wherever you do:
- IDE — set up your IDE with
ast-grep lspto seemessageas a diagnostic. - AI agent — a post-edit hook hands over the
agent_prompt, scoped to the lines it changed, so the agent fixes the violation before moving on. - Terminal —
ast-grep scanshows themessage.
ast-grep rules are byor's built-in kind; it also runs any linter, type checker, or
script you already use and folds their output into the same agent feedback. This
rule and others live in examples/, exercised in CI.
Install
uv tool install byor && byor install # install the CLI, then set up the skill + agent hooks (once)
byor init # optional — only for repo-scoped or shared rules (see below)
byor bundles ast-grep, so Python 3.11+ is all you need to run it — the rules
themselves work in any language ast-grep supports (TypeScript, Go, Rust, and
more), not just Python. byor install registers your editor and agent
integrations machine-wide. byor init is optional: run it only when you want
rules or checks scoped to a repository, or shared with contributors — your
personal global rules and checks already work in every repo without it.
docs/ai-agents.md covers what each step writes.
After that one-time bootstrap, let your AI coding agent handle the rest: open it
in the repo and say "set up byor". The skill verifies the install, runs
byor init if you want repo or team rules, and offers to import the preferences
you already wrote in your CLAUDE.md / AGENTS.md as enforced rules.
Terminal and editor
A rule under .byor/rules/ is an ordinary ast-grep rule, so the ordinary tools
read it:
ast-grep scan # lint the repo
ast-grep scan src/ # ...or a path
For live in-editor diagnostics, point your editor's ast-grep integration at
ast-grep lsp: rules light up as you type and reload when you edit them.
(editor setup.)
Rule scopes
The same rule format lives at three scopes:
| Scope | Lives in | Shared with |
|---|---|---|
project |
.byor/rules/project/ |
Your team (committed) |
local |
.byor/rules/personal/local/ |
You, this repo only |
global |
~/.config/byor/rules/ |
You, in every repo |
Global rules are your personal standards; byor makes them apply in every repo. Project and local rules override a global rule with the same ID, so a team policy or a local experiment takes precedence. See docs/rules.md for the rule workflow and docs/sync-model.md for how byor copies global rules into each repo.
With AI coding agents
Agents can both obey your rules and write new ones:
- Feedback. A post-edit hook runs
byor agent-checkafter the agent edits a file and feeds the diagnostics back into its context, scoped to the lines it changed, so it fixes violations before moving on. - Capture. A bundled skill turns durable feedback ("never do this", "always
do that") into an ast-grep rule: the agent drafts it, confirms once, and runs
byor add. When a linter or type checker fits better, the skill offers that instead. - Setup. The same skill onboards you: say "set up byor" and it checks the install, optionally inits the repo, and imports the mechanically checkable preferences from your existing CLAUDE.md / AGENTS.md as rules — and can clean up an existing repo on a throwaway branch so you start without a wall of warnings.
byor install wires up the agents you pick (once, machine-wide); byor hook
adds or drops one later.
byor install --agents claude-code,codex
byor hook install --agent copilot # add an agent later
byor hook uninstall --agent copilot # or remove one (--agent skill removes the skill)
byor supports five harnesses:
| Harness | Skill | Real hook | Diagnostic precision |
|---|---|---|---|
| Claude Code | yes | PostToolUse |
the edited lines |
| Codex | yes | PostToolUse |
the edited lines |
| Copilot CLI | yes | postToolUse |
the edited lines |
| OpenCode | yes | tool.execute.after plugin |
the changed file |
| Pi | yes | tool_result extension |
the changed file |
Cursor and Antigravity are not supported: neither exposes a post-edit hook that byor can reliably integrate with, so byor omits them until that changes.
A checks: section in .byor/config.yml (or your global config) runs extra
command-line tools (a linter, a type checker, anything) on the changed files and
folds their output into the same feedback. See
docs/ai-agents.md.
Continuous integration
Project rules are committed files that work with ast-grep, so CI doesn't need
byor: a fresh clone already has everything ast-grep scan reads. Scan with
--error so warnings fail the build (a plain scan exits 0 on warnings):
- run: npm install -g @ast-grep/cli
- run: ast-grep scan --error
Commands
Setup. You run these once to get going.
byor install Register byor's AI integrations (machine-wide)
byor init Initialize byor in a repository
byor hook Add or remove an agent integration
byor doctor Check that everything is wired up
Rules. Your agent runs these as it captures and manages rules for you.
byor add Create a rule in a scope
byor list Show rules and where they come from
byor edit Open a rule in $EDITOR
byor remove Delete a rule
byor promote Move a personal rule into shared project rules
byor exclude Disable a global rule in this repository
byor include Re-enable an excluded global rule
Automatic. byor runs these itself: the post-edit hook and self-heal.
byor agent-check Render diagnostics for your agent
byor sync Mirror global rules into the repo
Every command takes --help, and repo-operating commands take --repo PATH
(default: search upward from the current directory).
What's next
Today byor catches strays with one mechanism: a deterministic post-edit hook. That already covers anything a rule, a linter, or a type checker can express.
The harder strays are behavioral, not textual: an agent drifting off the plan you agreed on, stopping a loop early, editing files outside the scope you set. Teaching the sheepdog to herd those too is where byor is headed. If there is a rule you wish it could enforce, open an issue.
Documentation
- docs/rules.md — rule format, scopes, and the rule workflow
- docs/ai-agents.md — AI agent integration and
agent-check - docs/sync-model.md — copies, self-healing, and git hooks
- examples/ — reference rules (simple → advanced) and config setups
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 byor-0.1.5.tar.gz.
File metadata
- Download URL: byor-0.1.5.tar.gz
- Upload date:
- Size: 63.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4578451a5a6639dab602f9a420a3489f93a62cd349d42e77ff18ea5a526b8b85
|
|
| MD5 |
dc5b57b12ab373c842285eaf8f33ceb2
|
|
| BLAKE2b-256 |
b33201d48c81412719688cfdb72f00cc9772553f45e43cc12ab87502038b7fc8
|
Provenance
The following attestation bundles were made for byor-0.1.5.tar.gz:
Publisher:
release.yml on RyanSaxe/byor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
byor-0.1.5.tar.gz -
Subject digest:
4578451a5a6639dab602f9a420a3489f93a62cd349d42e77ff18ea5a526b8b85 - Sigstore transparency entry: 1874474701
- Sigstore integration time:
-
Permalink:
RyanSaxe/byor@17b76ad75810bec1d083cdab2bcd995798cf6d87 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/RyanSaxe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@17b76ad75810bec1d083cdab2bcd995798cf6d87 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file byor-0.1.5-py3-none-any.whl.
File metadata
- Download URL: byor-0.1.5-py3-none-any.whl
- Upload date:
- Size: 81.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37f6d5bf554b630e41bc429b772036ebc2479138326109886c73f4d134d615b4
|
|
| MD5 |
f28405186d135fe1daacb0ee317bf68f
|
|
| BLAKE2b-256 |
1c5639c8f616020441afcf10d0a1df5b30a44cde107c4804751ab154e12bc184
|
Provenance
The following attestation bundles were made for byor-0.1.5-py3-none-any.whl:
Publisher:
release.yml on RyanSaxe/byor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
byor-0.1.5-py3-none-any.whl -
Subject digest:
37f6d5bf554b630e41bc429b772036ebc2479138326109886c73f4d134d615b4 - Sigstore transparency entry: 1874474749
- Sigstore integration time:
-
Permalink:
RyanSaxe/byor@17b76ad75810bec1d083cdab2bcd995798cf6d87 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/RyanSaxe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@17b76ad75810bec1d083cdab2bcd995798cf6d87 -
Trigger Event:
workflow_dispatch
-
Statement type: