Ignore rules decide which paths Runi may name at all. An excluded file is not redacted, not summarised and not counted. It is absent from the event entirely, whether your agent read it or wrote it.
The four sources, combined#
-
Built-in secret globs#
Always on, in every repository, before anything else is consulted:
built-in.env .env.* *.pem *.key credentials.* secrets/** node_modules/** .git/** id_rsa* *.p12 *.pfx -
Your
.gitignore#Git owns
.gitignoresemantics, so in a real repository Runi asks Git instead of re-implementing it. Negations and nested rules behave exactly as they do for Git, because it is Git deciding. -
A
.relayignorein the repository root#The same familiar syntax, for things you want out of Runi but in Git. Committed to the repository, so it applies to everyone on the team without anyone configuring anything.
-
Patterns you add in the app#
Per machine, in the privacy settings. They ride into
~/.relay/config.jsonand are enforced by the daemon, not merely displayed by the UI.
A .relayignore#
# Client material that lives in the repo but must not leave the machine
clients/**
docs/contracts/**
# Fixtures with real-looking data
fixtures/production-*.json
# A single file
scripts/deploy-keys.ts
What the parser supports#
| Pattern | Matches |
|---|---|
*.log | Any .log file, at any depth. |
secrets/** | Everything under secrets/. |
build/ | A directory. The trailing slash expands to everything inside it. |
/local.ts | A leading slash is stripped. Matching is not anchored to the root. |
# comment | Ignored. |
Careful
Negation (!pattern) is not supported in
.relayignore. Lines starting with ! are skipped,
not re-included. This file only ever adds exclusions. A privacy control that
can be widened by a line further down is one you have to read to the end
before you can trust it.
Where each source applies#
| Folder | Rules consulted |
|---|---|
| A Git repository | Built-ins, your app patterns, .relayignore, and .gitignore via Git itself. |
| A folder with no Git metadata | Built-ins, your app patterns, .relayignore, and .gitignore parsed by Runi's own matcher. |
When Git cannot answer#
Occasionally Git cannot vouch for a path. A path outside the work tree is the usual case. Those paths are withheld: Runi does not publish something it could not confirm was safe to publish. The doctor records it as a warning instead of declaring the whole daemon broken:
warn ignore Git could not answer an ignore check (4 min ago) —
publishing continues; check that git runs in the repository
If you see this constantly, check that git is on the PATH the
agent runs with.
Testing a rule#
Add the pattern, run a session that touches the file, and check the app. Or, faster, use dry run. Nothing is published, and the event that would have been goes to stderr, where you can see whether the path appears at all:
$ DRY_RUN=1 node ~/.relay/daemon/hooks/claude.js < some-event.json
What ignore rules do not cover#
- Your prompt. If you paste a secret into a prompt, redaction is what protects you, not ignore rules. It runs on your machine before the event exists, and it matches known secret shapes. It is not omniscient.
- Whole repositories. To keep a project out entirely, do not track it. See Repositories.
- Records already published. Adding a rule changes the future. For the past, see Deleting your data.