Configuration
oboro reads the nearest oboro.toml, searching upwards from the working directory. Oboro matches the name exactly, in lower case, so a case-insensitive filesystem does not disagree with a case-sensitive one. Without one, it uses the defaults below. Every section is optional.
# Regions whose national phone number formats are read. Optional.
regions = ["FR", "GB"]
# Languages requested from Tesseract when reading images. Optional.
ocr_languages = ["fra", "eng"]
# The local recognition model.
ner_enabled = true
ner_threshold = 0.15
# Redact PII found in the input filename, not just the contents.
redact_filenames = true
# Values that must never be redacted.
allowlist = ["My Own Company Ltd", "Lille"]
# Terms that must always be redacted.
[[denylist]]
term = "Acme Consulting SARL"
kind = "provider"
# Your own identifier formats.
[[patterns]]
name = "contract number"
regex = "CT-[0-9]{6}"regions
Two-letter region codes that decide how Oboro reads national phone numbers. Oboro redacts a number when it is valid in any of them. So listing more regions widens what is caught, and listing none narrows it.
With FR, 06 12 34 56 78 is a valid mobile number. With GB alone, it is not, and Oboro leaves it alone. Oboro reads a number written in international form, such as +33 6 12 34 56 78, whatever this key holds, even when it is empty.
Leave the key out and the region comes from the environment’s locale (LC_ALL, then LANG), which oboro doctor reports:
regions: FR (from $LANG)
regions: FR, GB (from oboro.toml)
regions: none (international + numbers only)Set regions = [] to say deliberately that Oboro should read only international numbers. Oboro refuses an unknown code by name, rather than ignoring it, since a typo would otherwise cost every national number in the document.
Nothing else in detection consults this. Street addresses, postcodes and every checksummed identifier are matched by shape, in any language.
ocr_languages
Languages requested from Tesseract when reading an image, in order of priority, using Tesseract’s own three-letter codes (fra, eng, deu). Only used in a build with --features ocr.
Leave it out, and oboro reads whatever trained data is installed. It loads up to four languages together, English first when it is there. Past four languages, Oboro uses only one, since Tesseract loses both speed and accuracy as languages pile up. That is the point at which naming what your documents are in is worth it.
If you ask for a language with no trained data installed, Oboro reports it and lists what is installed, rather than failing obscurely inside Tesseract.
ner_enabled and ner_threshold
ner_enabled turns the recognition model off without rebuilding. ner_threshold is the probability a detection must reach before it is acted on.
Lower it to redact more, raise it to redact less. The default of 0.15 errs towards redacting, for reasons set out in Limitations.
redact_filenames
Whether Oboro redacts PII in the input filename, in the output name. On by default. With it on, jean@example.com.txt is written as EMAIL_1.clean.md, rather than leaking the address into the name.
The filename shares placeholders with the document body. So a name that appears in both gets the same tag. Workbook sheet names go through the same redaction, since each sheet’s name becomes part of its output filename. Placeholders appear without their brackets in the name (EMAIL_1, not [[EMAIL_1]]), to stay shell-safe. Set it to false to keep the original filename.
allowlist
Values that must never be redacted, whatever finds them. Your own company name belongs here, and so does anything the model keeps misreading as a name.
Matching ignores case and surrounding whitespace, and understands accents. So an entry of Société Générale matches SOCIÉTÉ GÉNÉRALE.
denylist
Terms that must always be redacted, whether or not anything else spots them. This is how you handle a client list you already know.
[[denylist]]
term = "Globex Industries"
kind = "company"
[[denylist]]
term = "Bell"
case_sensitive = truekind decides which placeholder the value gets. It defaults to organisation. Recognised values are person, organisation, address, phone and email, along with a few synonyms such as client, provider and company. Anything else becomes a placeholder of its own name.
Matching respects word boundaries. So Acme matches ACME but not acmentioned. It ignores case by default. Set case_sensitive = true on a term to match only its exact case. Use this to redact a short name such as Bell without also redacting the ordinary word bell.
patterns
Your own identifier formats, as regular expressions.
[[patterns]]
name = "contract number"
regex = "CT-[0-9]{6}"The name becomes the placeholder tag. So this one produces [[CONTRACT_NUMBER_1]]. Oboro treats patterns you declare as the most specific kind there is, because you declared them deliberately.
A pattern such as [0-9]{6} matches any six digits anywhere, including inside longer numbers. Prefer something with a distinctive prefix, or anchor it with \b.
The regular expression syntax is Rust’s regex crate. It has no backreferences and no lookaround. Oboro reports an invalid expression with the name of the pattern that contains it, rather than ignoring it.