What a brand means.
Authored, structured, shared.

Design tokens capture decisions. Brand guidelines capture rules. Neither captures intent: the authored reasoning that sits between what a brand does and why it does it that way. The voice, the stories, the rules about what to never say. Everything that makes every decision feel like it belongs to the same brand. Brand Intent is an open specification that gives this reasoning semantic structure, readable by humans and machines alike.

identity brand format purpose composition

The reasoning disappears. The brand drifts.

Brand teams write vision, mission, values. Then they jump straight to visual identity. The reasoning in between (why this typeface, why never say that word, why this audience matters more) lives in someone's head, a workshop deck, or page 47 of a PDF nobody opens after launch.

Guidelines try to bridge this gap, but they're fuzzy by design. "Be authentic." "Use a warm tone." Two designers reading the same guideline will produce two different things, both arguably on brand. There's nothing concrete to test against. And when the strategist leaves or the agency hands over, what survives are the outputs (colors, fonts, layouts) but not the logic that connected them.

AI didn't create this problem. It accelerated it. When a human designer works from fuzzy guidelines, they compensate with taste and context. When an AI does, it reaches for the generic. The gap between strategy and expression was always there. AI just made it produce output faster than anyone can course-correct.

Brand Intent is the missing layer: semantic structure for the reasoning that makes a brand specific.

Every brand system answers five independent questions.

Most tools collapse them into one document. Brand Intent keeps them separate. Each question has its own file type. Each file type has one job. That separation is what keeps the reasoning intact as expression evolves.

Who is this brand?
Identity
.identity
How is it expressed?
Brand
.brand
Where does it appear?
Format
.format
What is this content for?
Purpose
.purpose
How are elements composed?
Composition
.composition

Write your brand once. People and agents read the same source.

Brand Intent files are plain text that lives in your repo, version-controlled and diffable. Not a PDF that rots in a shared drive, not prompts you rewrite each session. Infrastructure that compounds over time.

1
Install the skill. npx brand-intent init teaches your AI agent how to read, compose, and validate Brand Intent files. Works with Claude Code, Cursor, Gemini CLI, Copilot, Codex CLI.
2
Author your brand. Write your .identity and .brand files once. Add purposes for each content type, formats for each platform. These files live in your repo, version-controlled and diffable.
3
Reference a purpose. Tell your agent: "write content for the daily-bread purpose, Instagram 4:5." It reads the layers, composes the context, enforces voice.never and pillars.avoid, and validates every slot against the spec.

No app required. Brand Intent files are plain text. The installed skill teaches agents how to compose the five layers into context. Without it, the files are still readable by any LLM you point at them.

A
Content generation. .identity + .brand + .purpose → any LLM. Voice rules, audience definitions, and pillar constraints keep output on-brand. The spec is the brief.
B
Design systems. .brand is the source of truth for colors, typography, spacing. Push tokens to Figma, not the other way around. Official Figma plugin coming soon.
C
Brand governance. voice.never, pillars.avoid, and anti-audience are machine-checkable rules. Validate generated content before publish. Brand compliance becomes automated.

From identity to composition, in plain text.

Identity

The strategic core. Essence, promise, positioning, mission, vision, archetype. Voice with machine-checkable always/never rules. Named narratives: the brand's stories, one marked primary. Values as behavior statements, not keywords. Content pillars. Audiences with language guidance. Anti-audiences as exclusion signals. Nothing visual. Nothing compositional.

krume.identity
# ── Positioning ──

essence:  Brot ist Handwerk, nicht Lifestyle. Mehl, Wasser, Zeit.
promise:  Wer reinkommt, riecht sofort, dass hier seit vier Uhr
          morgens jemand steht.
tagline:  Mehl, Wasser, Zeit.
positioning:  Krume ist die einzige Bäckerei im Kiez, die jedes
              Brot beim Mehl nennt, nicht beim Marketing.
mission:  Ehrliches Brot für den Kiez - jeden Tag, aus dem
          gleichen Ofen, mit den gleichen Händen.
vision:  Eine Nachbarschaft, in der niemand mehr erklären muss,
         warum gutes Brot sechs Euro kostet.
archetype: craftsman

# ── Narratives ──

narrative Mehl Wasser Zeit
  primary
  Gegründet 2019, als die Bäckerin ihren Agenturjob
  kündigte, um das zu tun, was sie jeden Morgen seit
  ihrem sechzehnten Lebensjahr getan hat: Brot backen.
  Der Laden in der Weserstraße war vorher ein Copyshop.
  Die erste Woche war der Ofen zu klein. Die zweite
  Woche war das Brot zu schnell ausverkauft.
  Beides hat sich nicht geändert.

narrative Achtzehn Stunden
  Das Brot entsteht in achtzehn Stunden. Kein Schritt
  wird abgekürzt, kein Mehl wird ersetzt. Drei Sorten
  am Tag, nicht dreißig. Was weg ist, ist weg - morgen
  gibt es neues.

narrative Weserstraße
  Die Weserstraße hat sich verändert. Die Mieten steigen,
  die Spätis verschwinden. Krume bleibt. Nicht weil wir
  uns gegen irgendwas stemmen, sondern weil der Ofen
  morgens um vier an ist und die Stammkunden um sieben
  vor der Tür stehen. Das ist der ganze Widerstand.

# ── Voice ──

voice
  register:  informal, Du
  persona:   Bäckerin hinterm Tresen - direkt, trocken, stolz auf das Handwerk
  rhythm:    kurze Sätze, konkrete Angaben, kein Erklären
  always:
    - Sauerteig, not "artisan bread"
    - konkrete Mehlsorten (Tipo 1, Roggen 1150) over "beste Zutaten"
    - Backzeit in Stunden, nicht "lange Teigführung"
    - Kiez-Bezug (Neukölln, Weserstraße) over "unser Standort"
  never:
    - Lifestyle-Sprache (kuratiert, handverlesen, Genussmoment)
    - "Artisan" oder "Craft" - wir sagen Handwerk
    - Englische Begriffe wenn ein deutsches Wort existiert

# ── Values ──

values
  Handwerk
    Wir benennen den Prozess, nicht das Ergebnis.
    Backzeit in Stunden, Mehlsorte beim Namen.
  Ehrlichkeit
    Kein Brot ohne Zutatenliste. Keine Versprechen
    die der Teig nicht halten kann.
  Kiez
    Der Laden gehört zur Weserstraße wie der Späti
    nebenan. Wir kennen die Stammkunden beim Namen
    und die Nachbarn beim Brot.

# ── Pillars ──

pillars
  primary:   Sauerteig, Handwerk, Zutaten, Kiez
  secondary: Saisonales, Nachhaltigkeit, Backwissen
  avoid:     Lifestyle-Gastronomie, Wellness-Ernährung, Influencer-Kultur

# ── Audiences ──

audience regulars
  label:       Stammkunden aus dem Kiez
  profile:     25-65, täglich oder wöchentlich, kennen die Sorten
  motivation:  ihr Brot, ihr Laden, verlässlicher Rhythmus
  language:    knapp, direkt, kein Erklären - die wissen Bescheid

audience newcomers
  label:       Neugierige und Laufkundschaft
  profile:     Touristen, neue Nachbarn, Marktbesucher
  motivation:  gutes Brot finden, verstehen was anders ist
  language:    einladend, konkret, erklärt ohne belehrend zu sein

# ── Anti-Audiences ──

anti-audience influencers
  label:       Lifestyle-Influencer
  description: Menschen die Brot als Aesthetic posten,
               nicht als Lebensmittel essen.

anti-audience discount-hunters
  label:       Schnäppchenjäger
  description: Wer den Preis eines Sauerteigbrots mit dem
               Supermarkt-Toastbrot vergleicht, ist hier falsch.

Brand

The derived expression intent. Colors, typography, voice constraints, content defaults. Not expression itself, but the authored conditions that determine what valid expression looks like.

krume.brand
id:       krume
name:     Krume
language: de
locale:   de-DE

# ── Color Primitives ──

brand-colors
  primary:   #2C1810   # dark roast
  secondary: #5C3A28   # walnut
  accent1:   #C8A47E   # crust
  accent2:   #8B4513   # rye
  white:     #FAF6F0   # flour

# ── Themes ──

theme Laden
  background:     $white
  text-primary:   $primary
  text-secondary: $secondary
  text-tertiary:  $accent1
  text-subtle:    #A89282
  text-muted:     #C4B5A7
  logo:           $primary
  sticker-bg:     $accent1
  sticker-fg:     $primary
  cta:            $accent2
  label-bg:       $accent1
  label-fg:       $primary
  icon:           $secondary
  divider:        $accent1

theme Tafel
  background:     $primary
  text-primary:   $white
  text-secondary: #D4C4B0
  text-tertiary:  #8A7A68
  text-subtle:    #6A5A48
  text-muted:     #4A3A28
  logo:           $accent1
  sticker-bg:     $accent2
  sticker-fg:     $white
  cta:            $accent1
  label-bg:       $accent2
  label-fg:       $white
  icon:           #D4C4B0
  divider:        $accent1

# ── Typography ──

font primary
  name:     Hanken Grotesk
  fallback: sans-serif
  source:   google

font secondary
  name:     ABC Stefan Simple
  fallback: sans-serif
  source:   local

typography display
  font:        $secondary
  weight:      400
  size:        8
  lineHeight:  1.1
  autofit-min: 5
  autofit-max: 12

typography headline
  weight:      700
  strong:      800
  size:        6
  lineHeight:  1.15
  autofit-min: 4
  autofit-max: 10

typography kicker
  weight:      400
  size:        2.6
  lineHeight:  1.3
  autofit-min: 2.5
  autofit-max: 3.5

typography quote
  weight:      700
  strong:      800
  size:        5.5
  lineHeight:  1.2
  autofit-min: 4
  autofit-max: 8

typography body
  weight:      400
  size:        2.8
  lineHeight:  1.5

typography caption
  weight:      400
  size:        2.2
  lineHeight:  1.4

typography attribution
  weight:         300
  size:           2.2
  lineHeight:     1.4
  letterSpacing:  0.08

typography label
  weight:      600
  size:        2
  lineHeight:  1.2
  uppercase

typography number
  weight:         300
  size:           14
  lineHeight:     0.9
  letterSpacing:  -0.03

# ── Spacing ──

spacing:
  unit: cqmin
  xs: 1.5
  s:  2
  m:  3
  l:  5
  xl: 6.5

# ── Dividers ──

divider line
  thickness: 0.15
  width:     100%
  color:     divider
  align:     left
  spacing:   s

divider ruler
  thickness: 0.8
  width:     20%
  color:     divider
  align:     left
  spacing:   m

Format

Platform, canvas dimensions, safe zones (danger / crop / comfort), grid spec, and which purposes are editorially valid for this surface.

instagram-4-5-feed-portrait.format
# Platform, dimensions, safe zones, grid spec.
# Knows nothing about content. Only where it appears.

id:       4:5
label:    4:5
sublabel: Feed Portrait
category: instagram

size:     1080 1350
grid:     5 4           # rows × cols

# ── Safe Zone Model ──
# danger → crop → comfort → content area

danger:   0 0 0 0       # always cropped by platform
crop:     0 34 0 34     # profile grid crops top/bottom
comfort:  40            # safe reading margin

# Which purposes are editorially valid for this surface.
purposes: daily-bread, seasonal-special, baking-tip

Purpose

Defines a content type through semantic slots (primary, secondary, meta, label, cta). Narrows the composed upstream with scope, adds slot-specific AI context, and purpose-level voice overrides. Palette control determines how colors are assigned.

daily-bread.purpose
id:   daily-bread
name: Tagesbrot
compositions: editorial, simple-stack
density: light
palette: dynamic

# ── Voice ──
# Purpose-specific writing rules for AI text generation.

voice
  headline-pattern: noun-first
  number-format:    digit
  sentence-max:     8

# ── Identity Composition ──

scope
  audience: regulars, newcomers
  pillars:  primary

context
  primary is the bread name, 1-3 words (e.g. "Roggenlaib").
  secondary is the weight and price ("750 g · 5,80 €").
  meta is one sentence: what makes this bread specific today.
  Never describe the bread as "delicious" or "special" -
  state a fact (flour type, fermentation time, seasonal ingredient).

# ── Slots ──

slot primary
  label:      Brotname
  typography: headline
  color:      text-primary
  maxLength:  30
  samples:
    - Roggenlaib
    - Weizenmisch
    - Dinkelvollkorn

slot secondary
  label:      Gewicht & Preis
  typography: kicker
  color:      text-secondary
  maxLength:  25
  samples:
    - 750 g · 5,80 €
    - 500 g · 4,20 €

slot meta
  label:      Beschreibung
  typography: caption
  color:      text-secondary
  maxLength:  100
  samples:
    - Roggen 1150, 18 Stunden Teigführung, Kümmel aus dem Wendland.
    - Tipo 1 aus der Drax-Mühle, 72 % Hydration.

slot label
  label:      Badge
  typography: label
  color:      label-fg
  maxLength:  20
  samples:
    - Heute frisch
    - Nur samstags
    - Neu im Laden

Composition

Slot-to-position mappings. Two modes: grid (explicit row/column placement) and flow (panels, stacks, sticky zones for content-driven arrangement). Zero brand-specific information.

editorial.composition (grid mode)
# Explicit row/column placement. Newspaper style:
# secondary above primary, label badge top-right.

id:    editorial
mode:  grid
image: full
logo:  top left

label      row 1  cols 3--4  right
secondary  row 2  cols 1--4  left center
primary    row 3  cols 1--4  left
meta       row 5  cols 1--3  left bottom
cta        row 5  cols 4--4  right bottom
simple-stack.composition (flow mode)
# Content-driven arrangement: sticky bars + flow regions.
# Vertical stack in a bottom panel over full-bleed image.

id:    simple-stack
mode:  flow
image: full

sticky: bottom s
  | logo right

flow: panel bottom-left 2/3 1/1
  | spacer-auto
  | label left
  | primary left
  | divider-line
  | secondary left
  | spacer-s
  | meta left
  | spacer-auto

Full specification on GitHub

Your brand as infrastructure.

1. Install the VS Code extension

Syntax highlighting, autocomplete, and hover docs for all five file types.

extinstall studiostoll.brand-intent-lang

Or download manually from the VS Code Marketplace.

2. Run init

Installs two skills into your AI agent: /brand-intent and /brief. Together they cover the full loop. Onboard your brand, explore the Krume bakery reference, generate and validate on-brand content, and export a portable brief.

$npx brand-intent init

Works with: Claude Code, Cursor, Gemini CLI, VS Code Copilot, Codex CLI

3. Use your brand

Once initialized, the two installed skills cover the daily loop. Edit your Brand Intent files whenever strategy or expression evolves. Regenerate briefs after any change.

  • /brand-intent authors, validates, and generates on-brand content from your Brand Intent files.
  • /brief exports a portable {brand-id}-brief.md. Use it to hand the brand to a tool that doesn’t read Brand Intent directly, like a Claude Design project, another LLM, or a collaborator.

What the skills can do

Onboard your brand (/brand-intent onboard). A guided interview covers essence, voice (always/never rules), colors, typography, audiences. Your AI agent asks the questions, then scaffolds .identity + .brand + a starter .purpose.

Explore the example (/brand-intent example). The Krume bakery brand, a fully commented reference showing all five layers. Identity, brand expression, format, purpose, composition.

Generate & validate (/brand-intent). Compose context from all five layers and generate on-brand content for any purpose. Validate against voice rules, pillars, and anti-audiences.

Export a portable brief (/brief). Generate a single markdown file derived from your Brand Intent files. It stays format-agnostic, usable with any LLM, human, or tool. For example, drop it into a Claude Design project as brand context.