Set up repository rules

Review proposed rules, adopt them through a pull request and read advisory verdicts on your changes.

On this page

Repository rules turn your team's coding expectations into checks on pull requests. Each rule lives in your repository as a Markdown explanation and a matching Jev evaluation file. ArchDev proposes candidates; you review the files and merge a rules PR to adopt them.

Violations appear on the archdev.ai PR page. They are advisory: ArchDev does not post them to GitHub or block merging.

Find your first candidates

Connect your GitHub repository, then open https://archdev.ai/OWNER/REPO/rules, replacing OWNER/REPO with your repository. Repositories whose names begin with a dot, such as .github, are supported.

The Candidates section shows proposals and their evidence. Expand a candidate to inspect its drafted files. Candidates can add a rule, update an existing pair or retire one. The Active rules section shows the selected rule files at the default-branch revision displayed on the page, with links to their source files.

Drafting starts right away when you add a repository to an existing GitHub App installation. For a brand-new installation, the first PR triggers the initial draft. Drafting runs nightly after that.

ArchDev drafts candidates from instruction files such as AGENTS.md and CLAUDE.md. If a repository has fewer than five instruction candidates and uses Elixir, Go, TypeScript/JavaScript, Python or Rust, ArchDev also proposes starter rules. That count includes open candidates, candidates in open PRs and adopted candidates; dismissed candidates do not count. Archived repositories and forks do not receive starter proposals. A starter proposal needs the same review and merged PR as any other candidate.

No rule files means no repository-rule checks. Instruction files and candidates alone do not activate checks.

Configure

You can use the default rule directory without adding configuration. To choose what ArchDev reads and where rules PRs put files, commit .archdev/rules.yaml:

Code
include:
  - ".archdev/rules/**/*.jev"
exclude:
  - ".archdev/rules/retired/**"
adopt_to: ".archdev/rules/"
draft_from:
  - "AGENTS.md"
  - "CLAUDE.md"
Field What it controls
include Repository-relative patterns selecting rule pairs. Defaults to .archdev/rules/**/*.jev; selecting a .jev also reads its sibling .md.
exclude Patterns removing rule files and instruction sources. Defaults to []. Excluding either sibling makes a rule pair incomplete.
adopt_to Directory where candidate adoption PRs write rules. Defaults to .archdev/rules/. If you change it, also update include to select that directory.
draft_from Instruction sources for candidate drafting. An explicit list replaces the defaults; [] disables instruction-file drafting, but does not disable active rules or starter proposals.

The example keeps only AGENTS.md and CLAUDE.md as instruction sources. When customizing draft_from, list AGENTS.md again if you still want it read.

Without draft_from, the standard sources include root AGENTS.md, CLAUDE.md, GEMINI.md, .cursorrules, .windsurfrules, .github/copilot-instructions.md, and .cursor/rules/ Markdown and .mdc files. Nested AGENTS.md, CLAUDE.md and .cursor/rules/ patterns are also selected by default, but drafting skips nested sources.

Patterns support *, ** and ?. Use repository-relative paths; absolute paths, .., brace expansion and negated patterns are unsupported. Each include pattern must start with a literal directory, such as .archdev/rules/, rather than a repository-wide wildcard.

ArchDev drafts only root-level instruction files, .github/copilot-instructions.md and root .cursor/rules/ files. Nested instructions and custom instruction folders are not drafted, even if a draft_from pattern matches them. Collection is limited to 16 files, 128 KiB per file and 256 KiB total.

Write a rule pair

Use the same filename stem for both files. Put language-specific candidates under elixir/, go/, typescript/, python/ or rust/ beneath adopt_to; use technologies/ for cross-language rules.

This Python example checks YAML loading from external input. Save the explanation as safe-yaml.md in your working directory while preparing the proposal:

Code
---
name: "Use safe YAML loading for external input"
description: "Do not construct Python objects when parsing request or uploaded YAML."
date: 2026-10-14
---

# Use safe YAML loading for external input

Use `yaml.safe_load` for request or uploaded YAML. Check changed production
code; exclude test fixtures and trusted local configuration. Report a
violation only when the diff shows external input reaching an unsafe loader.

These examples illustrate the rule; they are not repository incidents.

Violation:

```python
data = yaml.load(request.body, Loader=yaml.Loader)
```

Compliant:

```python
data = yaml.safe_load(request.body)
```

Save its evaluation template as safe-yaml.jev:

Code
{
  "model": "jev-latest",
  "state": {
    "diff": "REPLACE_BEFORE_USE: PR diff",
    "context": "REPLACE_BEFORE_USE: PR title, description and changed-file list"
  },
  "questions": {
    "applicable": {
      "type": "noul",
      "instructions": "Does state.diff show changed Python production code parsing YAML from request bodies or uploaded external input, using any loader? Exclude test fixtures and trusted local configuration. Judge scope only, independently of whether the loader is safe. Use state.context only to clarify scope."
    },
    "complies": {
      "type": "noul",
      "instructions": "Does the changed behavior in state.diff avoid constructing Python objects when parsing request or uploaded YAML? A visible call to yaml.unsafe_load or yaml.load with Loader or UnsafeLoader on that input violates the rule. yaml.safe_load complies. Exclude test fixtures and trusted local configuration. Use only state.diff and state.context; do not infer unchanged code. Answer yes if evidence is missing or ambiguous."
    }
  }
}

The Markdown frontmatter supplies the rule's name, description and date; the body explains the obligation, exceptions and examples. Cite real source lines when a proposal comes from an instruction or correction. Label synthetic examples as illustrative.

The .jev file is JSON, with exactly the model, state and questions fields shown above. Keep the REPLACE_BEFORE_USE: placeholders in the committed template: the checker supplies the PR diff and context. The two noul questions ask independently whether the rule applies and whether the change complies. A safe loader is still applicable to this rule.

Propose rules from Claude Code

Install ArchDev and sign in, then ask Claude Code to brainstorm rules for your repository:

Paste into your agent
Help me turn our instruction files and this session's corrections into repository rules. Read .archdev/rules.yaml, draft Markdown/Jev pairs with specific scope and examples, and show me each proposal before saving it as an ArchDev candidate. Include only the relevant correction as evidence.

To save the example pair as a candidate, replace acme/widget-api with your connected repository:

Code
archdev rules propose \
  --repository acme/widget-api \
  --theme-key safe-yaml \
  --md-file safe-yaml.md \
  --jev-file safe-yaml.jev \
  --proposed-path .archdev/rules/python/safe-yaml.md \
  --correction "Use safe YAML loading for request and uploaded input."

Use your configured adopt_to in --proposed-path. Proposing saves an inert candidate and pending evidence; it does not add files or change policy. Keep secrets and unrelated session text out of the correction. Candidate reconciliation may take time.

Read candidates and their theme keys with:

Code
archdev rules candidates --repository acme/widget-api

Adopt candidates through one PR

On the rules page, review the evidence and drafted changes, select the candidates you want, then choose Open rules PR. ArchDev opens one PR as your GitHub user containing the selected additions, updates and retirements. You can dismiss a candidate you do not want.

From a session, use the same theme keys returned by rules candidates:

Code
archdev rules pr --repository acme/widget-api safe-yaml

Pass multiple theme keys to put several candidates in one rules PR. Review the resulting diff and merge it through your normal repository process. Opening the PR does not adopt its rules into the default branch, though checks on that PR can already use its rule files. The rules adopt command records adoption evidence; it does not create the rule files or replace rules pr.

Merging the rules PR applies the rule files immediately. Candidate labels may still show the open PR until the next sweep marks them adopted; that status delay does not delay the rule files taking effect. Future policy edits and removals also go through reviewed, merged PRs.

Read verdicts on a change

Open your code PR on archdev.ai and confirm its current head. The checker reads .archdev/rules.yaml and selected pairs at that PR head; the rules page's inventory represents the default branch. An existing feature branch needs the merged rule files in its head to use them.

When a rule violation is shown, expand it to inspect the explanation, cited lines and rule text. A clean, complete check may show no violation banner. Missing, partial or unavailable checks are not proof of compliance. If the rules page lists invalid pairs, fix the named path and reason; both sibling files must be present and valid.

These verdicts are separate from risk grades. They remain advisory on archdev.ai, with no GitHub comment, required check or merge block. Follow your team's review process and inspect the evidence yourself.

Check a change before you merge · Merge and PR follow-up