.scribe/config.toml holds versioned project settings. It lives in Scribe's
.scribe/ namespace at the repository root, where everything except
.scribe/_state/ is ordinary versioned content; .scribe/_state/ remains local
workspace state. It is the only shared configuration path Scribe reads, spelled
exactly that way (see one spelling). .scribeignore keeps its
separate, directory-scoped discovery behavior.
version = 1
kind = "art"
[locks]
rules = [
'*.uasset',
'*.psd',
'!Art/Generated/**',
]
[profiles.programmer]
include = ['engine', 'game']
[profiles.artist]
include = ['game', 'art-source']
[profiles.everything]
include = ['.']
[presentation]
cover = 'Marketing/key-art.psd'
[tags]
"Characters" = ["character"]
"Environments/Forest" = ["forest", "environment"]Add, edit, and submit this file through ordinary Scribe commands. To create it
by hand, run mkdir -p .scribe first, then scribe add .scribe/config.toml, or
start from a preset. Its exact bytes determine its content identity; different formatting remains different versioned
content even when it represents the same settings. There is no alternate file
reader, automatic conversion, include directive, or environment expansion.
Format and validation
The file uses TOML, decoded by one shared parser and typed model in
scribe-api::repository_config. The server and clients use the same validation.
version = 1is required. Unsupported versions and unknown fields or sections are rejected, including unknown fields within lock, profile, mount, and presentation tables.- The entire file must be UTF-8 without NUL bytes, at most 64 KiB. Standard TOML comments, quoting, arrays, LF, and CRLF work normally. Duplicate keys or tables and values of the wrong type are errors.
kind,[locks],[profiles],[mounts],[presentation], and[tags]are optional. A missing file means agenericrepository with no mandatory locking, no named profiles, and no repository mounts. An existing file must be valid configuration; empty text is not a valid document.- The server validates the complete proposed file on every branch before
acceptance. Invalid configuration returns a recorded
invalid_repository_configoutcome; it never partially activates valid sections.
Repository kind
The optional top-level kind says what the repository holds, so clients can
choose how to present it. Values are lowercase strings:
| Value | Meaning |
|---|---|
generic | Default when kind is absent. Clients use their general presentation. |
art | An art and asset bank: meshes, animations, textures, audio. |
Any other value, spelling ('Art'), or type is rejected. Only the accepted value
on main counts; a kind on another branch has no effect until it is accepted
on main. Changing the decoded value on main requires a Maintainer, like lock
rules and mount topology (see section authority); writing
the default kind = "generic" explicitly, or removing that line, is not a
change. The kind does not affect storage, locking, or sync. In the
web interface, the auto Interface
preference opens art repositories in the Art interface.
Presentation
[presentation] shapes how clients show the repository, and nothing else: it
does not affect storage, locking, or sync.
| Key | Meaning |
|---|---|
cover | A repository path whose picture stands for the repository on its card |
cover must be a valid repository path by the same rules as every other path
in this file; an empty or malformed value, or any other key in the table, is
rejected. Only the accepted value on main counts. Any file that gets a
thumbnail can be the cover (an image, a PSD, a model's render, a video frame).
While the file is not on main, or has no thumbnail yet, the web interface
keeps its own choice: the newest file with a thumbnail. Like profiles, a Writer
may change it.
Tags
[tags] gives files tags for finding and grouping assets, and nothing else: it
does not affect storage, locking, or sync. Each key is a folder, and every file
in that folder or anywhere below it gets the listed tags. A key naming a file
rather than a folder gives nothing.
[tags]
"Characters" = ["character"]
"Environments/Forest" = ["forest", "environment"]
"Props/Vehicles" = ["vehicle", "prop"]- A key is a repository folder path in its exact repository spelling, by the
same rules as every other path in this file. An empty key,
., a leading or trailing/, and..are rejected, as are two keys that are the same folder to Scribe, such asCharactersandcharacters. A key naming a file, or a folder spelled differently from the repository (such ascharactersforCharacters), gives no file any tags. - At most 256 folders, each with a list of 1 to 32 tags. An empty list, or a value that is not a list of strings, is rejected.
- Each tag has 1 to 64 characters, is not only white space, and contains no
control characters or commas. Nothing else is checked. (The web interface
also bounds the lowercase spelling at 64 characters, so a tag made of the
rare letters whose lowercase is longer, such as
İ, can pass here and still be refused there; the configuration then shows as unreadable.)
Scribe keeps each tag exactly as written. The web interface normalizes it
(lowercase, single spaces, so " Hero Ship " and hero ship are one tag) and
shows these as rule tags in the asset catalog. Only the accepted value on
main counts. Rules label files for every collaborator, so changing them on
main requires a Maintainer, like kind and lock rules (see
section authority). The comparison is of the folders and
tags as written: changing character to Character is a change even though
the web shows both as one tag, while reformatting, reordering folder keys, or
adding comments is not. Reordering the tags within one folder's list is a
change.
Lock rules
locks.rules is an ordered array of at most 1,024 strings. Missing locks or
rules, and rules = [], mean no mandatory lock rules. Each pattern must be
nonempty, contain no control characters, and fit Scribe's maximum path length.
Comments belong in TOML outside strings, not in rule entries.
Patterns use Git-style matching with one difference: they ignore case and
Unicode normalization, comparing rule and path under the same fold Scribe uses
for path collisions, so *.psd also locks Hero.PSD
(two paths that fold alike are one file to Scribe, and a lock must not miss
either spelling). Otherwise: filename
matching at any depth for patterns without /, root anchoring with a leading
/, and last matching rule wins. ! makes matching paths optional; a trailing
/ selects the subtree. Single-quoted TOML strings preserve glob backslashes
literally, for example '\#special'. Ignore traversal does not apply: a subtree
rule cannot hide a later exception. See mandatory locks.
The fold is full Unicode case folding, applied to the pattern text and to the
path before matching, and it can turn one character into several: ß folds to
ss, fi to fi. Literal text is unaffected, so Straße/* locks
STRASSE/a.psd too. The wildcards are not: ? and a […] class match one
character of the folded text. Stra?e does not match Straße (folded
strasse), and [ß] folds to [ss], a class matching a single s. Write
such names literally, or use *.
scribe lock rules displays the active ordered rules. A path argument explains
the deciding rule and its actual line in .scribe/config.toml.
Workspace profiles
Each [profiles.NAME] requires an include array with at least one nonempty
string. Names contain 1–64 ASCII letters, digits, -, or _, are case-sensitive,
and are limited to 128 profiles per file. Each profile allows at most 256
inclusion prefixes. Paths use exact canonical spelling and Scribe's portable
path rules; . explicitly selects the entire repository.
There are no profile glob patterns, exclusions, or inheritance. Mount declarations
use separate [mounts.NAME] tables; profile prefixes select their paths.
Duplicate prefixes and redundant child inclusions are collapsed. The final
resolved selection also has a 256-prefix limit, including local additions and
the config file, which profile selections always include.
scribe workspace create game ./work --profile programmer
cd work
scribe sync
scribe workspace profiles
scribe workspace view set --profile artist
scribe workspace view set --profile programmer --view art-source/CharactersProfiles are resolved from accepted history at the selected branch head, even outside the current view. Unsubmitted edits do not redefine them. A workspace saves the resolved selection and local overrides; ordinary sync does not silently apply later profile edits. Reapply the profile explicitly to adopt changes and reset overrides. See workspace views for safe transitions, interruption, and cancellation.
Section authority
| Section | Effective source | Permission on authenticated servers |
|---|---|---|
kind | Accepted main | Maintainer when the value changes on main |
locks | Accepted main, governing every branch | Maintainer when the ordered rule values change on main |
profiles | Accepted selected branch revision | Writer to submit changes |
presentation | Accepted main | Writer to submit changes |
tags | Accepted main | Maintainer when the folders or tags change on main |
mounts | Accepted selected branch revision | Maintainer when the mount topology changes on main, Writer to advance a pin; targets enforce their own access |
A Writer may change profiles on main, or reformat and comment the file, while
retaining the same decoded kind and ordered lock-rule strings. Quote style, table
order, and source line numbers do not change the lock permission requirement. Changing
rule values or their order requires a Maintainer on main. Removing nonempty
rules by deleting the section, emptying the array, deleting the file, or moving
it away has the same requirement. A profiles-only file with no rules can be
created or removed by a Writer. Creating or removing a file with kind = "art"
on main likewise requires a Maintainer, as does creating or removing one with
[tags] rules.
Mount topology carries the same requirement, for the same reason: adding,
removing, renaming, or retargeting a [mounts.NAME] table decides where every
collaborator's nested workspace lives on disk. Advancing a mount's revision
stays a Writer action, so ordinary project publishing is unaffected.
The same checks cover ordinary submits and merges. A merge into main that
keeps main's .scribe/config.toml unchanged, taking none of the source
branch's config edits, needs no Maintainer, whatever the source branch did to
the file. Writers can submit lock-rule
proposals on other branches, but those rules do not become active until a
Maintainer accepts them on main. Local files, historical working copies, and
profile selections cannot override active lock policy or repository permissions.
The active old rules govern the submission changing the config; removing rules
never releases existing locks.
Authorization compares the proposed kind and ordered rules with the exact config revision the changeset replaces. Acceptance rechecks that base under the publication gate, so a concurrent config change causes a base mismatch instead of bypassing lock permissions. Configuration reads, parsing, and rule matching happen outside the metadata write transaction. No accepted history is rewritten.
Repository mounts
Use [mounts.NAME] with path, repository, branch, and a decimal-string
revision to pin an independent repository. A configuration declares at most
64 mounts; a 65th is rejected even when the file stays within the 64 KiB limit.
Paths cannot overlap other mounts or parent files. A mount path cannot name a
.scribe directory (in any letter case) or lie inside the root .scribe/, so
.scribe, .scribe/engine, and engine/.scribe are all rejected. See
versioned repository mounts for selection, child
permissions, sync recovery, SDK access, and web browsing.
One spelling
The configuration path is exactly .scribe/config.toml. Scribe's path rules
already refuse two tracked paths that differ only by case or Unicode
normalization; in addition, the server refuses a submit on any branch that adds
or changes a case or normalization variant such as .Scribe/config.toml or
.scribe/Config.toml. Such a file would look like configuration and govern
nothing, so it is rejected with invalid_repository_config rather than silently
ignored.
Starting from a preset
Repository creation stays an administrative action (scribe repo create); there
is no web page for creating repositories. To seed the configuration for an art
repository, create the first workspace with a preset:
scribe workspace create art-bank ./art-bank --preset art
cd art-bank
# Review .scribe/config.toml in your editor, then:
scribe submit -m "Configure art repository"--preset art writes .scribe/config.toml into the new working copy and opens
it for add. Nothing is submitted; the configuration takes effect only when you
submit it, with the usual permissions (a Maintainer on main, because it sets
kind and lock rules). The command is refused, before any workspace is created,
when main already has an accepted .scribe/config.toml; edit that file
instead. Without --profile, the --view prefixes must include .scribe/config.toml. An existing
file at the path in the working copy is never replaced. The preset writes
exactly:
# Repository configuration; see Scribe's docs/repository-config.md.
version = 1
# Clients present an art repository as an asset bank.
kind = "art"
# Binary sources and interchange formats cannot be merged: whoever edits one
# holds its lock until they submit. Rules ignore case; the last match wins.
[locks]
rules = [
# Painting and texturing
"*.psd", "*.psb", "*.kra", "*.spp", "*.sbs",
# 3D scenes and sculpts
"*.blend", "*.ma", "*.mb", "*.max", "*.c4d", "*.hip", "*.hiplc", "*.ztl", "*.zpr",
# Interchange
"*.fbx", "*.abc", "*.usd", "*.usdc",
# Engine assets
"*.uasset", "*.umap",
]