Beta·every release is a pre-releaseAPIs and harness behavior are still changing·every release until v1 is a pre-release
uzev1 beta
Package manager

Rules

Instructions that arrive only where they apply

AGENTS.md reaches every agent whole, whatever it is touching. A rule reaches it only when it matters: when the agent opens a file under src/ui/, or when the task is a migration. Write each one once, in .agents/rules/, and every agent reads it.

---
trigger: glob
globs: "**/src/ui/**/*.rs"
---

Colours come from the theme: name a `Token`, never an RGB value.

Where rules live

One Markdown file per rule, directly under .agents/rules/ in your project, committed with it. Each file's frontmatter says when it applies; the rest of the file is the rule.

A subfolder is read only when .agents/rules.json registers it, which is how Antigravity reads it, and so uze and the rules engine too:

{"entries": [{"path": ".agents/rules/team"}]}

Each entry's path is relative to the root of the project, not to the manifest. A folder entry reads the *.md files directly in it, and a file entry reads that one file. include_only and exclude list paths relative to the entry. A file registered twice is still one rule. A manifest that does not parse registers nothing, and uze status says so. inherits is not followed: uze reports it, because the rules it reaches arrive in Antigravity alone.

When a rule arrives

triggerArrivesNeeds
globwhen the agent reads, edits or writes a file matching globsglobs
model_decisionas one line of an index; the agent reads the rule when the task calls for itdescription, written as when to read it
always_onat the start of every sessionnothing more
manualonly when someone points the agent at itnothing more

Most rules are glob. Keep always_on rare: it costs every session, and text that is always true usually belongs in AGENTS.md.

Patterns

globs is one pattern, or several separated by commas. Quote it when it starts with *. Each pattern is either:

  • a file name, with no /, which matches at any depth: *.sql, Makefile
  • a path that starts with **/: **/src/ui/**, **/migrations/*.sql

Inside a pattern, ** matches any number of whole directories, * matches within one name, ? matches one character, and [ab] or [0-9] matches one character of a set. Any other character, spaces included, is matched literally, except the ones listed below.

A rule must match the same files in every agent, so uze reports a pattern that could be read two ways, rather than deliver the rule to some agents and not others:

  • a / in a pattern that does not start with **/: Antigravity matches against the file's full path, so src/ui/** would never fire there
  • braces ({a,b}): write two patterns instead
  • ! anywhere, a negated set ([^a]), or an empty or unclosed [
  • (, ), | or \
  • a leading /, a . or .. segment, an empty segment (a//b) or a trailing /
  • ** that is not a whole segment, as in src/**.ts
  • an empty pattern, whitespace other than a space, or a control character

Write a rule as a convention

Say what the project does, not what the agent must answer: "Handlers return Result<_, ApiError>", not "You MUST always reply with…". Keep one concern per file and keep it short. The uze:rules skill guides an agent through writing one:

/uze:rules

How each agent receives them

AgentRoute
Antigravityreads .agents/rules/ and .agents/rules.json itself, with or without uze
Claude Codethrough the rules engine uze setup installs
Codexthrough the rules engine; a path named only inside a shell command is found on a best-effort basis
OpenCodethrough the rules engine

The engine reads your project's own .agents/rules/ and .agents/rules.json each time, so a branch or a checkout with different rules gets its own. The engine copies nothing into your project, and nothing is compiled. On Windows the engine is not available yet, and uze status says so.

Share rules through a plugin

When the same conventions hold for every repository of a team, write them once in a plugin instead of copying files between projects. A plugin ships rules as Markdown files directly under its rules/ directory, in the same format. The uze:author skill scaffolds one for you, and checks the rules before you install it. Patterns are matched against paths relative to the project that receives the rule.

Declaring the plugin

In a project, uze acme-conventions@acme (or uze install, once the plugin is in agents.yaml) copies each rule, byte for byte, into the project:

.agents/rules/acme-conventions@acme/ui.md
.agents/rules/acme-conventions@acme/testing.md

and registers the folder in .agents/rules.json, creating it when there is none:

{
  "entries": [
    {
      "path": ".agents/rules/acme-conventions@acme"
    }
  ]
}

The folder names the plugin the files belong to. Every agent reads them exactly as it reads your own rules, and a rule of yours with the same name is left alone. uze adds and removes only its own entries in the manifest and writes every other entry and key back unchanged. If the manifest does not parse, uze leaves it as it is, copies nothing and says so. Rules are the one part of a plugin that never reaches an agent machine-wide: uze install -m reports them as delivered per project, and a project that does not declare the plugin never receives them.

An always_on rule is how a plugin says something to every agent of every project that declares it.

Commit the copies

The copies are ordinary project files. Commit them and .agents/rules.json beside agents.lock: a clone, a worktree or CI then has the rules without running uze, and Antigravity reads them there natively.

Updates and drift

uze update acme-conventions moves the lock to the plugin's new revision and rewrites its copies to match. Rules the new revision changed show up as modified files in your pull request, and rules it dropped as deleted ones, so a change to the conventions is reviewed like code. uze remove acme-conventions deletes the plugin's copies, its folder and its entry, and the manifest too once nothing else is left in it. Your own rules stay.

A copy is current when it matches the plugin's rule at the revision agents.lock pins. uze status reports each plugin's rules as current, or names every file that is drifted (edited), missing, or extra (in the plugin's folder but not shipped by it). It can do that on a fresh clone too: when this machine does not have the plugin, it reads the pinned revision without installing anything, and without network it reports the copies as unverified.

uze never overwrites or removes a copy someone edited. uze install and uze update name it and leave it. To resolve it, either revert the file, or take ownership of the change by moving it out of the plugin's folder into .agents/rules/, which makes it one of your project's own rules. A missing copy is restored by uze install.

Check them

uze status says how many rules of each kind the project has, any file that is not a rule and why, each declared plugin's rules and whether their copies match the lock, and how each installed agent receives them. It never prints a rule's text. An offline check that fails a build is in Agent CLI.

In the workspace, the harness's details under Manage and the agent's overview (Alt+O) show .agents/rules beside AGENTS.md: Native, Rules engine, Run uze setup when the engine has not been installed for that agent yet, or Not supported.

On this page