dsc theme¶
Install (from git or a local bundle), delete, list, pull, push, and duplicate themes; read/write a theme's settings, fields (SCSS/HTML), and upload assets; enable/disable and attach/detach components; and update git-backed remote components.
dsc theme list¶
Lists installed themes on the specified Discourse. -v/--verbose includes additional fields where supported.
dsc theme install¶
Installs a theme/component via the admin import API (POST /admin/themes/import.json). <source> is either:
- a git repo URL - imported by the server. Private repos work by embedding credentials in the URL (
https://user:TOKEN@github.com/org/repo.git); the token is redacted in--dry-runoutput.--branch/-bselects a branch (defaults to the repo's default). - a local bundle file - a
.tar.gz/zip theme export, uploaded and imported.
dsc theme install myforum https://github.com/org/theme
dsc theme install myforum https://user:TOKEN@github.com/org/private-theme.git -b main
dsc theme install myforum ./my-theme.tar.gz
dsc theme delete¶
Deletes a theme/component by id via the API (DELETE /admin/themes/:id.json). Refuses to delete the site default theme (reassign the default first). Honours -n / --dry-run. Prefer this over theme remove - it needs no SSH setup.
dsc theme remove¶
Legacy SSH removal by name, using the command template in DSC_SSH_THEME_REMOVE_CMD (supports {name} and {url} placeholders). Prefer dsc theme delete <id>, which uses the API and needs no SSH template.
dsc theme pull¶
Pulls the specified theme into a local JSON file. <theme-id> can be found using dsc theme list.
If <local-path> is omitted, the file is written to the current directory named from the theme name (slugified). The path to the written file is printed to stdout.
dsc theme push¶
Pushes a local JSON theme file to a Discourse instance.
- If
<theme-id>is supplied, updates that existing theme. Updating a live theme is destructive (it upserts the theme's fields), so it requires--yes; review the plan with--dry-run(-n) first. Prints the ID on success. - If the JSON file contains an
idfield,dscrefuses to guess: pass that ID explicitly as<theme-id>to update, or remove theidto create a new theme. This prevents a file pulled from one forum from silently overwriting a same-numbered theme on another. - Otherwise (no
<theme-id>, noidin the file) creates a new theme and prints the new ID.
dsc theme duplicate¶
Duplicates the specified theme and prints the new theme ID. The copy is named Copy of <original name> and is not set as the default theme. --format json emits {"id": ...}.
dsc theme show¶
Shows a richer view of one theme/component than list: whether it's a theme or component, its enabled/default/user-selectable flags, colour scheme, parent themes, attached child components, settings count, and the editable field inventory (e.g. common/scss). Read-only.
dsc theme setting¶
Read and write a single theme or component's settings - the typed key/value pairs a component declares (e.g. a nav component's menu items). Distinct from dsc setting, which manages site-wide settings.
dsc theme setting list <discourse> <theme-id> [--format text|json|yaml]
dsc theme setting get <discourse> <theme-id> <key> [--format text|json|yaml]
dsc theme setting set <discourse> <theme-id> <key> <value> [--dry-run]
list/getread from the theme JSON (GET /admin/themes/:id.json).listprintskey = valueper line in text mode;json/yamlinclude each setting'stypeanddefault.setwrites viaPUT /admin/themes/:id/setting.json. The<value>is sent verbatim - for a JSON-schema list setting (e.g. a header-links component), pass the JSON array text directly, quoted for your shell. Honours global-n/--dry-run.
dsc theme setting get accm 11 links_position
dsc theme setting set accm 14 links_position left
dsc theme setting set accm 14 header_links '[{"id":1,"title":"Education","url":"https://..."}]'
dsc theme setting pull / push¶
For a whole component - and especially for the big JSON-list settings like a nav component's header_links / dropdown_links - snapshot the settings to a file, edit, and push back. The same pull → edit → push loop dsc setting pull/push gives site settings.
dsc theme setting pull <discourse> <theme-id> [<local-path>]
dsc theme setting push <discourse> <theme-id> <local-path> [--dry-run]
pullwrites every setting to a file (YAML by default; a.jsonpath writes JSON). JSON-list settings are expanded to real arrays -header_linksbecomes an editable list of entries, not one escaped string on a line. If<local-path>is omitted it writes<theme-name>-settings.ymlin the current directory.pushre-serialises each list back to the JSON-string form Discourse expects and PUTs only the settings that changed (compared semantically, so reformatting and key-order don't count as edits - an untouched pull → push is a clean no-op). Settings in the file that no longer exist on the component are skipped with a warning.--dry-runprints the plan, summarising long list values by length so the terminal isn't flooded.
This replaces the read-whole-array → change-one-field → PUT-it-back scripting that editing a header menu by hand otherwise needs.
# Snapshot the Dropdown Header component (id 17), edit, preview, apply
dsc theme setting pull accm 17 header.yml
$EDITOR header.yml # rename "Conference 2026" -> "2027" in the list
dsc theme setting push accm 17 header.yml --dry-run # header_links: changed (864 -> 868 chars)
dsc theme setting push accm 17 header.yml
dsc theme field¶
Read and write a theme's individual fields - the raw source entries a theme stores: common/scss, desktop/scss, mobile/scss, common/head_tag, etc. This is the pull -> edit -> push loop for a theme's SCSS/HTML, without a whole-theme JSON round-trip.
dsc theme field list <discourse> <theme-id> [--format text|json|yaml]
dsc theme field pull <discourse> <theme-id> <target/name> [<local-path>]
dsc theme field push <discourse> <theme-id> <target/name> <local-path> [--dry-run]
listshows each field astarget/namewith its type (scss/html/js/yaml/upload) and size.pullwrites one field's body to a file (default name derived from the field, e.g.common-scss.scss). Upload-var fields have no text body - usedsc theme assetfor those.pushPUTs just that one field back (a single-entrytheme_fieldsupsert; other fields are untouched). Unchanged content is a no-op;--dry-runshows the byte delta.pushrefuses a git-backed remote component - its fields are owned by the upstream repo, not the site. Edit upstream anddsc theme update, ordsc theme duplicateit first for an editable copy.
dsc theme field list accm 11
dsc theme field pull accm 11 common/scss common.scss
$EDITOR common.scss
dsc theme field push accm 11 common/scss common.scss --dry-run
dsc theme field push accm 11 common/scss common.scss
dsc theme asset¶
Upload an image or font and bind it to a theme upload variable ($name) in one step, so the theme's SCSS/settings can reference it.
dsc theme asset list <discourse> <theme-id> [--format text|json|yaml]
dsc theme asset set <discourse> <theme-id> <name> <file> [--dry-run]
dsc theme asset unset <discourse> <theme-id> <name> [--dry-run]
setuploads<file>, then binds it as atheme_upload_varfield named<name>on thecommontarget - referenceable as$namein the theme's SCSS.listshows the theme's bound upload assets (name, filename, URL).unsetremoves a binding (deletes thetheme_upload_varfield).- Site-wide header logos (
logo,logo_small,mobile_logo) are site settings, not theme assets - set those withdsc setting set+dsc upload.theme assetis for theme-scoped$varimages/fonts.
dsc theme asset set accm 11 centred_logo ./logo.png
dsc theme asset list accm 11
dsc theme asset unset accm 11 centred_logo
dsc theme enable / disable¶
Toggles a theme or component's enabled state (PUT /admin/themes/:id.json). A disabled component stays attached to its parents (disabled is not the same as detached). Honours -n / --dry-run.
dsc theme attach / detach¶
dsc theme attach <discourse> <parent-id> <component-id>
dsc theme detach <discourse> <parent-id> <component-id>
Attaches or detaches a component to/from a parent theme - this is what makes a component active on a given theme (and what dsc theme install leaves to you). dsc reads the parent's current children, adds/removes the component, and writes the full replacement set, so other attached components are preserved. Detaching an id that isn't attached (or attaching one that already is) is a reported no-op. Honours -n / --dry-run.
# Make component 14 active on the default theme (id 2)
dsc theme attach accm 2 14
# Retire it again
dsc theme detach accm 2 14
dsc theme update¶
Pull a git-backed remote component to its latest upstream commit - the CLI equivalent of the Admin UI's "check for updates" / "update" on a remote theme. Distinct from dsc update, which rebuilds the OS/Discourse host.
--check(and--dry-run) reports how many commits behind upstream the component is, without pulling.- Without
--check, it pulls the latest commit and reports the old -> new short hash (or "already up to date"). - Only git-backed remote components can be updated; a locally-authored theme reports a clear error (it has no upstream).