Configuration
stylist separates two kinds of configuration:
- Style rules (allowed colors/fonts, banned terms) live in the ruleset: versioned domain data, owned by the brand team.
- Operational config (which ruleset, where the API is, failure behavior) is resolved per invocation as described here.
Precedence
Section titled “Precedence”Highest wins:
- Command-line flags (
-ruleset, …) STYLIST_*environment variables- The project file
.stylist.yaml, found by walking up from the working directory (like.gitignoreor.golangci.yml) - Built-in defaults
.stylist.yaml
Section titled “.stylist.yaml”Checked into the repo root:
ruleset: rules/brand.yaml # path in local mode; ruleset ID in api_url modeapi_url: https://stylist.internal # optional: check via the core APIbaseline: .stylist-baseline.yaml # optional: auto-discovered if presentfail_open: true # default true — see belowaudience: external # optional: "internal" or "external" — see belowoverrides: # optional: skip specific admin-permitted rules — see below terms: banned: ["legacy-slogan"]Relative ruleset/baseline paths resolve against the config file’s
directory, so checks behave identically from any subdirectory.
Environment variables
Section titled “Environment variables”| Variable | Meaning |
|---|---|
STYLIST_RULESET |
Ruleset path (local) or ID (remote) |
STYLIST_API_URL |
Core API base URL; enables remote mode |
STYLIST_API_TOKEN |
Bearer token for the core API (env-only) |
STYLIST_BASELINE |
Baseline file path |
STYLIST_FAIL_OPEN |
true/false, overrides fail_open |
STYLIST_AUDIENCE |
internal/external, overrides audience |
STYLIST_LICENSE |
License key (server side, unlocks the dashboard) |
STYLIST_DASH_TOKEN |
Dashboard sign-in token (server side) |
Secrets (STYLIST_API_TOKEN, STYLIST_LICENSE, STYLIST_DASH_TOKEN)
are deliberately not read from .stylist.yaml: checked-in files
must never carry credentials. A YAML key like api_token: is ignored.
Fail-open
Section titled “Fail-open”fail_open: true (the default) means: when checking is impossible —
the API is unreachable, the ruleset file is missing, config is broken —
hooks warn and allow the operation rather than blocking work. Actual
style violations always block regardless.
Set fail_open: false to invert this for strict environments; the hook
then exits 2 when checking is impossible.
Audience
Section titled “Audience”audience: internal or audience: external declares whether the
assets a project/invocation checks are internal-only or client-facing.
It’s admin-declared, not inferred. An invalid value (anything besides
internal/external) is rejected at load time. Leaving it unset
is a legitimate “not yet classified” state, not an error.
Also settable per invocation with -audience (CLI) or STYLIST_AUDIENCE
(env), same precedence as every other setting. It’s surfaced on the
dashboard’s “By audience” breakdown and in each asset’s check history,
and it can also gate which rules apply. See Audience-scoped
rules. Leaving it unset applies
every rule regardless of audience scoping (the safe default: an
audience-scoped rule only ever gets dropped by declaring the other
audience, never added by leaving it blank).
A loose asset is one-off, agent-generated content with no
.stylist.yaml to declare audience: in (see Loose
assets). For a loose asset, audience can also be
declared in-content instead of via flag/env; see Context
nudges.
Rule overrides
Section titled “Rule overrides”overrides: declares which specific rules of a centrally-governed
ruleset this project asks to skip. It’s a plain disable list: an
override only ever relaxes a rule, it never adds one.
overrides: colors: true # skip the whole colors block fonts: false images: false terms: banned: ["legacy-slogan"] # skip by the term's own text required: [] outdated: logos: ["old-logo-2019"] # skip by name colors: ["#ff0000"] # skip by value fonts: []It only takes effect for rules the ruleset itself marked
overridable: true. See Per-project rule
overrides for how a ruleset
opts a rule into this, and for how requests against unauthorized rules
get reported: never silently swallowed, never an error either. The
check just runs as if the request had never been made.
Unlike audience, overrides is file-only: there’s no
-overrides flag or STYLIST_OVERRIDES env var, since it only ever
makes sense as a per-project, checked-in policy decision, never a
per-invocation one. Like audience, it only matters against a
centrally-governed ruleset (api_url mode). A local ruleset file is
already fully under the project’s own control, so there’s nothing to
relax that editing the file directly wouldn’t already do.
Local vs remote mode
Section titled “Local vs remote mode”With no api_url, checks run in-process against a local ruleset file.
With api_url set, ruleset names a server-side ruleset ID, content
is POSTed to the core API, and the verdict comes back over HTTP. The
CLI, hooks, output, and exit codes are identical in both modes.