Skip to main content

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

byor: Build Your Own Rules

CI PyPI Python versions License

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.

byor is 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: Parameters after the first two must be keyword-only. Two positional
  parameters is a maximum, not a target; one or zero can be clearer.
utils:
  positional-param:
    any:
      - kind: identifier
      - kind: typed_parameter
      - kind: default_parameter
      - kind: typed_default_parameter
  counted-param:
    all:
      - matches: positional-param
      - not: { regex: ^(self|cls)$ }
      - not:
          follows:
            stopBy: end
            any: [{ kind: keyword_separator }, { kind: list_splat_pattern }]
rule:
  kind: parameters
  has:
    all:
      - matches: counted-param
      - follows:
          stopBy: end
          all:
            - matches: counted-param
            - follows: { stopBy: end, matches: counted-param }
metadata:
  byor:
    agent_prompt: >
      Insert a bare `*` after the last positional parameter so every later
      argument is keyword-only, for example def f(a, b, *, c, d). self and cls
      do not count; parameters before a `/` do. Do not pick a signature
      mechanically: choose zero, one, or two positional parameters by how call
      sites read. A natural order like add(2, 3) or a single obvious subject
      like save_user(user) reads well positionally; booleans, config values,
      and parameters of the same type belong after the `*`.

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 lsp to see message as 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.
  • Terminalast-grep scan shows the message.

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. On a repo the team has not adopted byor for, byor init --private keeps the whole footprint out of git (nothing tracked, ignored via .git/info/exclude); see docs/sync-model.md. 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.

Tags in metadata.byor.tags are arbitrary labels you own. byor uses them for listing, profile setup, and repo-local exclusions; it does not reserve any tag names. Use byor list --tags to see the vocabulary already present in a repo.

Profiles are named templates in your global config that apply private repo-local exclusions at init time, or later with byor profile add. They are useful when a repo should opt out of broad groups of global rules or checks without deleting those personal standards everywhere:

profiles:
  existing:
    description: Low-friction defaults for mature repositories.
    rules:
      excluded_tags:
        - legacy-risk
    checks:
      excluded_tags:
        - strict

Packages are the opposite of a global rule: a named bundle of rules (and optional checks) under ~/.config/byor/packages/ that a repo opts into rather than getting everywhere automatically. byor package add <name> installs one for you in a repo (personally, like a local rule — not committed); promote its rules or checks with byor promote to share them with the team. Reach for a package when a rule set is reusable but too situational to force on every repo. See docs/rules.md.

With AI coding agents

Agents can both obey your rules and write new ones:

  • Feedback. A post-edit hook runs byor agent-check after 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):

- uses: astral-sh/setup-uv@v6
- run: uvx --from ast-grep-cli ast-grep scan --error

byor init --gate generates this workflow and a matching .pre-commit-config.yaml for you — promoting your effective rules and checks into committed config first, so the gate stays byor-free but also covers your checks. See docs/sync-model.md.

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 init --private Keep byor to yourself; commit nothing (git info/exclude)
byor init --gate    Distribute a byor-free pre-commit + CI gate to the team
byor hook           Add or remove an agent integration
byor doctor         Check that everything is wired up
byor profile        List or apply configured profiles
byor package        List or install opt-in rule/check packages

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/package rule or a check into shared config
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

Project details


Download files

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

Source Distribution

byor-0.3.0.tar.gz (92.3 kB view details)

Uploaded Source

Built Distribution

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

byor-0.3.0-py3-none-any.whl (118.3 kB view details)

Uploaded Python 3

File details

Details for the file byor-0.3.0.tar.gz.

File metadata

  • Download URL: byor-0.3.0.tar.gz
  • Upload date:
  • Size: 92.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for byor-0.3.0.tar.gz
Algorithm Hash digest
SHA256 546023e7372985771925c31d0b332bfb23aa2236ef13ec1e7ca2a08e1e0d1671
MD5 bab1af4d95253af05d98eb10fb89ee8a
BLAKE2b-256 a2367fa4bd5ec36a45c7d1fe1b0fc8f7262b51aaa34d746e205215ab22758f79

See more details on using hashes here.

Provenance

The following attestation bundles were made for byor-0.3.0.tar.gz:

Publisher: release.yml on RyanSaxe/byor

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

File details

Details for the file byor-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: byor-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 118.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for byor-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8d7d5a65126d823f7d4cbc8b5a581e69401def718ed8bba006c259f94eab77b4
MD5 af5919c6c3ac3252f012b7c483b551e9
BLAKE2b-256 1e7374ab5060a9fe1fef4804fc38cde6f37940a6c27460360dbb8c0cda60ce5e

See more details on using hashes here.

Provenance

The following attestation bundles were made for byor-0.3.0-py3-none-any.whl:

Publisher: release.yml on RyanSaxe/byor

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 Pingdom Monitoring Sentry Error logging StatusPage Status page