---
title: "Preset codes"
description: "The short code that carries a whole theme, how opsinjs namespaces its own, and how to encode, decode and apply one."
url: "https://opsinjs.pensievelabs.org/registry/preset-codes"
source: "https://opsinjs.pensievelabs.org/registry/preset-codes.md"
section: "Registry & distribution"
kind: "guide"
reviewed: "2026-09-20"
reviewer: "engineering"
aliases: ["preset code", "decode", "apply theme", "share a theme"]
---

> Elements written as `<PascalCase … />` below are opsinjs documentation
> components. Their attributes are the content: the values they render are
> generated from `tokens/*.json` and `registry/catalogue.ts` and are
> published separately at https://opsinjs.pensievelabs.org/r/index.json and under the Reference
> section.
> `<StubNotice>` IS THE EXCEPTION, AND IT IS THE ONE TO READ. It is a
> paired element rather than a self-closing one, and the text between
> its opening and closing tags is prose an author wrote, reproduced
> below word for word. That prose is where this page says whether the
> component has been reviewed. Read the children, not only the
> attributes.

<PageTemplate kind="guide" />

## Overview [#overview]

A preset code is a short opaque string that stands for a complete theme
configuration: style, base colour, icon library, font and radius. It exists so
that "use this theme" can be six characters in a chat message rather than a
paste of a stylesheet.

opsinjs uses two related things and it is worth separating them immediately:

* **shadcn preset codes** are opaque short codes the shadcn CLI decodes and
  applies. This documentation site was itself initialised from one.
* **opsinjs preset names** are readable, namespaced names such as
  `opsinjs-default`, served as registry items at `/r/themes/<name>.json`.

The first is a compact wire format for shadcn's own configuration space. The
second is a theme in the opsinjs sense, which is a larger thing: role tokens for
both themes, shape, spacing, the P3 escalation.

## Decode before you apply [#decode-before-you-apply]

Never apply a code you have not decoded. It is opaque by design, and applying
one modifies your stylesheet and your `components.json`.

<CodeBlockTabs defaultValue="npm" groupId="package-manager">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx shadcn@latest preset decode <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx shadcn@latest preset decode <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx shadcn@latest preset decode <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x shadcn@latest preset decode <code>
    ```
  </CodeBlockTab>
</CodeBlockTabs>

It prints the style, base colour, theme, chart colour, icon library, font and
radius the code stands for. Reading that output takes two seconds and is the
difference between a deliberate change and a surprising one. The named `lyra`
preset, for instance, brings a different icon library and a monospace UI font,
which is not obvious from the name and was exactly the surprise this project
avoided by using the code form instead.

Related commands:

<CodeBlockTabs defaultValue="npm" groupId="package-manager">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx shadcn@latest preset resolve
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx shadcn@latest preset resolve
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx shadcn@latest preset resolve
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x shadcn@latest preset resolve
    ```
  </CodeBlockTab>
</CodeBlockTabs>

Prints the preset your project currently matches. That is the fastest answer to
"what theme is this project actually on".

<CodeBlockTabs defaultValue="npm" groupId="package-manager">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx shadcn@latest preset url <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx shadcn@latest preset url <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx shadcn@latest preset url <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x shadcn@latest preset url <code>
    ```
  </CodeBlockTab>
</CodeBlockTabs>

<CodeBlockTabs defaultValue="npm" groupId="package-manager">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx shadcn@latest preset open <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx shadcn@latest preset open <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx shadcn@latest preset open <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x shadcn@latest preset open <code>
    ```
  </CodeBlockTab>
</CodeBlockTabs>

The URL for the code, and the same thing opened in a browser.

## Apply one [#apply-one]

<CodeBlockTabs defaultValue="npm" groupId="package-manager">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx shadcn@latest apply <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx shadcn@latest apply <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx shadcn@latest apply <code>
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x shadcn@latest apply <code>
    ```
  </CodeBlockTab>
</CodeBlockTabs>

To take only the colours, or only the typography, without reinstalling
components:

<CodeBlockTabs defaultValue="npm" groupId="package-manager">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx shadcn@latest apply <code> --only theme
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx shadcn@latest apply <code> --only theme
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx shadcn@latest apply <code> --only theme
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x shadcn@latest apply <code> --only theme
    ```
  </CodeBlockTab>
</CodeBlockTabs>

`--only` accepts `theme` and `font`. In an existing opsinjs project this is
almost always what you want: a full apply may touch component-level
configuration you have already tuned.

<Callout>
  `apply` edits `app/globals.css`. The order of that file is load-bearing. The
  generated token layer sits at a fixed position and the `dark` variant is pinned
  last on purpose. After applying anything, re-read the file's own header comment
  and check that the structure survived. See
  [Tailwind v4](../theming/tailwind-v4.mdx).
</Callout>

## The opsinjs preset name format [#the-opsinjs-preset-name-format]

opsinjs preset names are readable and namespaced:

```
opsinjs-<name>
```

Every one begins with `opsinjs-`, for the same reason the registry namespace is
`@opsinjs`: shadcn publishes its own style names, and a collision would be
silent and unresolvable. The full argument is in
[Presets](../theming/presets.mdx) and in [Namespaces](./namespaces.mdx).

A preset name resolves to a registry item:

<CodeBlockTabs defaultValue="npm" groupId="package-manager">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npx shadcn@latest add https://opsinjs.pensievelabs.org/r/themes/opsinjs-default.json
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm dlx shadcn@latest add https://opsinjs.pensievelabs.org/r/themes/opsinjs-default.json
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn dlx shadcn@latest add https://opsinjs.pensievelabs.org/r/themes/opsinjs-default.json
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun x shadcn@latest add https://opsinjs.pensievelabs.org/r/themes/opsinjs-default.json
    ```
  </CodeBlockTab>
</CodeBlockTabs>

Unlike a shadcn code, the name is not compressed and carries no hidden fields.
The JSON it resolves to is the whole configuration, readable, in one request.
That is a deliberate trade: longer to type, impossible to be surprised by.

## Encoding your own [#encoding-your-own]

<StubNotice
  name="opsinjs-preset-encode"
  issue="prashantonomy/opsinjs#0"
  questions="[
  &#x22;Does an opsinjs code carry the full role set, or a delta against the default?&#x22;,
  &#x22;What happens when a code is applied to a project whose token version is older than the code?&#x22;,
  &#x22;Is a code allowed to carry a status-ramp override at all?&#x22;,
]"
/>

Producing a shareable code from a theme you have built is specified and not
implemented. Today, the shareable artefact is the registry item: generate a
theme in [the theme generator](../theming/theme-generator.mdx), export it as
`registry:item` JSON with `cssVars`, and serve it. That works now, works
everywhere, and needs no encoder.

The third question in the block above is the one that matters. A code that can
silently redefine the clinical status ramp is a code that can change what a
screen asserts about somebody's health by being pasted into a terminal. The
likely answer is no. See [Status palettes](../theming/status-palettes.mdx).

## Verify it worked [#verify-it-worked]

<Steps>
  ### Decode matches your intent [#decode-matches-your-intent]

  `preset decode` before, `preset resolve` after. The two should describe the same
  configuration.

  ### The stylesheet still has its structure [#the-stylesheet-still-has-its-structure]

  Confirm the generated token import is still in position and there is exactly one
  active `@custom-variant dark` declaration, at the end.

  ### The status ramp did not move [#the-status-ramp-did-not-move]

  `--opsin-status-urgent-line` should be unchanged by any theme operation. If it
  moved, something wrote outside the role tier.
</Steps>

## Troubleshooting [#troubleshooting]

**`apply` changed more than the theme.** Use `--only theme`.

**A code is rejected as invalid.** Codes are version-sensitive; one produced by a
much older or newer CLI may not decode. Pin the CLI version that produced it.

**`preset resolve` prints nothing recognisable.** The project has drifted from
every known preset. That is normal after hand edits, and not an error.

**A named preset and a code disagree.** They are different systems. The name
resolves to opsinjs JSON; the code resolves to shadcn configuration. Prefer the
name for anything opsinjs-specific.

## Next [#next]

* [Presets](../theming/presets.mdx) is the theming-side view.
* [registry-item.json](./registry-item-json.mdx) is the shape a preset takes on
  the wire.
* [Self-hosting a fork](./self-hosting-a-fork.mdx) covers serving your own
  presets.
