SyncTERM themes are INI files which define user-interface styles and glyphs. The C host loads one theme for the process and exposes immutable snapshots of it to the menu, file-picker, and connected Wren VMs. All three VMs therefore start with the same program-wide theme.
Storage and Selection
Theme files use the .ini extension and live in the per-user themes
directory beside the per-user scripts directory. The exact path is shown
by SyncTERM Settings → File Locations. Typical locations are:
| Platform | Directory |
|---|---|
Windows |
|
macOS |
|
Unix |
|
Haiku |
The user’s settings directory followed by |
The selected basename is stored as ThemeFile in the [SyncTERM] section of
syncterm.ini. Paths are not accepted. A theme installed from the online
catalog is instead stored as ThemePackage, using a stable identifier such
as official/dark-mode. ThemeFile and ThemePackage are mutually
exclusive. Selecting the built-in Classic Theme removes both keys instead
of storing a special name.
At startup, a missing or invalid selected file or cached package falls back to Classic Theme without deleting the configured identity. The appropriate theme browser displays that selection as invalid so it can be diagnosed after the file or package is restored. The browser previews valid themes as the highlight moves, saves a selection on Enter, and restores the committed theme on Escape. Invalid entries remain highlightable for their error text but cannot be selected.
The six settings under [ClassicTheme] affect only the built-in Classic
Theme. A file theme is a sparse overlay on SyncTERM’s compiled default and
does not inherit those six colour preferences.
Online Themes
The Themes browser lists the built-in Classic Theme, local theme files, and
packages which have been downloaded into the cache. F6 opens Online
Themes, which lists only manifest packages without a cached copy. Enter
downloads and selects an online package, F2 downloads it as an unsaved local
copy in the theme editor, and F5 refreshes the manifest and downloaded
packages. Cloud packages are read-only cache entries; editing one creates an
ordinary file in the per-user themes directory which is no longer
associated with manifest updates. Both browsers show the highlighted
theme’s Description on the main-screen comment line. Delete removes a local
theme file or cached package; deleting the selected theme first selects
Classic Theme. A deleted cached package returns to Online Themes.
The official manifest and its packages are stored below
syncterm-system-cache/themes/official in SyncTERM’s cache directory. This
keeps automatically managed files separate from manually installed themes.
Files ending in .download are HTTP cache bodies. SyncTERM promotes a body
to manifest.lst or <id>.ini only after validation, so an invalid response
does not replace the last accepted copy. Clearing the system cache removes
downloaded packages but does not remove ThemePackage from syncterm.ini.
SyncTERM falls back to Classic until that package is available again.
Once an online catalog has been used, SyncTERM checks it during startup. Packages already present in the cache, including the selected package, are updated when their manifest SHA-256 changes. Entering the Online Themes browser also checks for updates. A network or validation failure retains the previous validated package and is shown in the browser.
The official catalog is read from
http://syncterm.bbsdev.net/themes/manifest.lst. Its contents use INI
syntax:
Repository = official
Name = SyncTERM Themes
[Theme:dark-mode]
Name = Dark Mode
Author = Example Author
Description = A dark theme
Version = 1.0
URI = http://syncterm.bbsdev.net/themes/dark-mode.ini
SHA256 = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Repository must occur exactly once and currently must be official.
Section suffixes are stable package IDs containing only lowercase ASCII
letters, digits, periods, underscores, and hyphens. Name, an absolute HTTP
or HTTPS URI, and a 64-digit SHA256 are required. Author, Description,
and Version are optional. Duplicate package sections or duplicate
recognized fields make the complete manifest invalid. The
SHA-256 identifies the exact theme file bytes; after the hash matches, the
normal theme loader must also accept the file before it can be installed.
Classic Extended
Classic Extended retains the default Classic Theme’s legacy 16-colour attributes role for role. On RGB-capable backends it expands the familiar blue, cyan, yellow, grey, and red scheme with additional shades for focused, inactive, input, status, help, log, and popup roles.
Official Colour-Vision Themes
The official catalog includes ten palettes for colour-vision conditions. Each theme defines every built-in style in both RGB and legacy 16-colour form. Legacy attributes keep bit 7 clear, so they do not request blinking text on VGA-compatible backends. Focus, inactive, disabled, input, status, warning, and popup states are reinforced by luminance or reversal rather than hue alone.
| Condition | Theme |
|---|---|
Protanomaly |
Emberworn |
Protanopia |
Emberless |
Deuteranomaly |
Verdantworn |
Deuteranopia |
Verdantless |
Tritanomaly |
Azureworn |
Tritanopia |
Azureless |
Red-cone monochromacy |
Crimsonbound |
Green-cone monochromacy |
Viridianbound |
Blue-cone monochromacy |
Ceruleanbound |
Achromatopsia |
Ashen |
Theme Editor
The Themes browser accepts Insert to create a theme and F2 to edit the highlighted theme. New themes begin as minimal sparse overlays on the compiled default. The built-in Classic Theme cannot be modified in place; editing it creates an unsaved copy which must be given a filename. A file which is not accepted by the current theme loader remains visible in the browser for diagnosis, but cannot be selected or opened in the editor.
The editor’s atlas contains every style role and glyph in the draft. Show Glyphs / Show Styles changes the kind of definition shown. Show Legacy / Show RGB changes the style colour display, and Show ASCII / Show CP437 changes the glyph display; the title reports the active mode. CP437 mode shows each glyph with its hexadecimal byte value, while ASCII mode shows the printable fallback and its decimal value. Preview opens an interactive screen of real menu, list, form, input, selection, button, progress, and status widgets using the unsaved draft theme. The preview’s outer frame retains the installed theme so it remains usable even when the draft is incomplete or unreadable. Its status line identifies the role used by the focused widget; F2 closes the preview and selects that role in the atlas. The inspector shows each resolved style field and the role which supplied it. Cascade shows every role considered for all four fields, including absent and inherited entries and the winning source. Enter or a double click edits the selected definition; Insert creates a custom definition and Delete removes one.
A built-in style field has three possible states:
-
Default removes the file’s value and uses the compiled value for that role. A compiled
inheritvalue continues through the role cascade. -
Inherit writes
inheritand explicitly continues through the role cascade. -
Explicit stores the selected value in the theme file.
Built-in glyph fields support Default and Explicit. CP437 values are
selected from a 16 by 16 grid of all byte values. ASCII fallbacks are
selected from a 16 by 6 grid containing space through tilde. The raw CP437
grid always uses font slot 0 so a draft style’s font cannot change the
meaning of the cells. Arrow and page keys wrap through each grid; Enter or
double click accepts and Escape cancels. Custom style and glyph definitions
are stored in full and can be removed. Metadata edits the global Name,
Author, Description, and Version values.
Import replaces all style and glyph sections with those from another theme as one undoable operation. This includes custom definitions, comments, ordering, and unknown fields in those sections. The destination filename and global metadata are retained. Importing Classic Theme synthesizes its current complete set of definitions.
Undo and Redo apply only to the current editing session. Save writes without closing the editor and starts a new undo session. Save As accepts a basename in the themes directory; paths are not accepted. Closing a dirty document asks whether to save, discard, or continue editing. Safe mode permits browsing but does not permit saving.
The editor preserves comments, ordering, unrecognized metadata, unrecognized sections, and unmodified values from an opened file. Values changed through the editor are rewritten in the normal theme syntax. Before replacing an opened file, Save compares its source lines with the lines originally read and asks before overwriting an external change. New destinations also require confirmation before replacement. The completed output is parsed and validated before an atomic replacement is attempted.
File Structure
Metadata is written before any section header:
Name = Example Theme
Author = Example Author
Description = A short description shown in the Themes browser
Version = 1.0
[Style:default]
Foreground = 0xFFFFFF
Background = 0x000040
[Style:list.item.focused]
LegacyAttr = 0x70
Foreground = 0x000000
Background = 0xC0C0C0
[Glyph:scrollbar.thumb]
CP437 = 219
ASCII = 35
Name is required and must not be empty. Author, Description, and
Version are optional. Duplicate recognized metadata keys are errors.
Unrecognized metadata, sections, and keys are ignored for forward
compatibility.
Recognized section names and keys are case-insensitive. Two recognized sections with the same name, including names which differ only in case, make the file invalid. A malformed value or duplicate recognized key also makes the file invalid.
Styles
A [Style:role] section may contain these fields:
| Field | Range | Meaning |
|---|---|---|
|
|
Conio font slot. |
|
|
IBM text attribute used by legacy-colour backends. |
|
|
24-bit RGB foreground used by RGB-capable backends. |
|
|
24-bit RGB background used by RGB-capable backends. |
Numbers use C integer syntax, so decimal and 0x hexadecimal forms are
accepted. The case-insensitive value inherit clears a field and makes it
inherit through the Wren role cascade. Omitted fields retain the compiled
default value for an existing role; a new role starts with all fields set to
inherit.
Role lookup removes dotted suffixes until it reaches default. For example,
list.item.focused falls back through list.item, list, and default.
Roles ending in .inactive use the parallel inactive cascade before falling
back to default. The resulting default style must contain all four
fields, so a file which clears one of its fields without replacing it is
invalid.
The current role registry is:
| Role | Use |
|---|---|
|
Cascade terminators and general screen/pane colours. |
|
Pane and dialog borders. |
|
Pane and dialog border titles. |
|
Command-menu rows. |
|
List rows, including the selected row in an unfocused pane. |
|
Text-input fields. |
|
Button labels and their shortcut character. |
|
Status and help bars. |
|
Check-box controls. |
|
Radio-button rows. |
|
Numeric spin controls. |
|
Menu bars and their entries. |
|
Scrollbar track and position indicator. |
|
Filled portion of a progress bar. |
|
Transfer and diagnostic log severities. |
|
Markdown help content. |
|
Status and alert popups. |
|
Main-menu screen chrome. These roles are optional in file themes and
otherwise cascade to |
Scripts may use additional role names. A theme file may style such a role before it becomes part of the built-in registry.
Glyphs
A [Glyph:name] section uses numeric byte values:
-
CP437is0..255and identifies the primary CP437 glyph. -
ASCIIis a printable ASCII byte,32..126, used when the primary glyph cannot be rendered.
Literal characters are not accepted because many CP437 glyphs are control
codes, whitespace, or not representable in the theme file’s encoding. An
existing glyph may override either value. A new glyph name must provide both
CP437 and ASCII.
The built-in glyph registry is:
| Name | CP437 | ASCII |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Scripts may define and use additional glyph names, subject to the requirement that a new name supplies both byte values.
Compatibility
The role and glyph registries may grow as UI widgets are added. Unknown content is ignored so a file can include entries understood by newer SyncTERM versions, while sparse overlays automatically receive new compiled defaults. Theme authors should still test both RGB and legacy-colour output, because every visible style can be rendered through either representation.