A CLI theme manager for Typora — install, uninstall, list, and validate Typora themes from the command line. Inspired by Homebrew's formula model.
typora-theme-manager helps you manage Typora themes from the command line. Each theme lives in its own JSON (or JSONC) file under themes/, making it easy to add, review, and version-track theme definitions — like Homebrew Formulae.
- Install / uninstall themes by variant ID
- List all available themes with install status and upgrade info
- Validate theme definition files against schema
- i18n: English, Simplified Chinese, Traditional Chinese — auto-detected or set via
TTM_LANG - Zero third-party dependencies — Python standard library only
- JSONC support — write
//comments and trailing commas in theme files
- Python 3.9+
- Typora installed
git clone https://github.com/witt-bit/typora-theme-manager.git
cd typora-theme-managerNo pip install, no virtual environment required.
Add the repo directory to your PATH to use the ttm shortcut from anywhere:
# Linux / macOS — add to ~/.bashrc or ~/.zshrc
export PATH="$PATH:/path/to/typora-theme-manager"
# Windows (PowerShell) — add to your $PROFILE
$env:Path += ";C:\path\to\typora-theme-manager"The wrapper scripts auto-detect your Python 3 installation:
ttm— Linux / macOS (bash)ttm.cmd— Windows CMDttm.ps1— Windows PowerShell
# List all themes
ttm list
# Install a theme by variant ID
ttm install phycats
# Uninstall
ttm uninstall phycats
# Validate all theme files
ttm validate
# Validate a specific file
ttm validate themes/my-theme.jsonc
# Check and upgrade installed themes
ttm upgrade
# Auto-upgrade without confirmation
ttm upgrade --no-confirm
# Switch language
TTM_LANG=en ttm list
TTM_LANG=zh_CN ttm listTheme files live in themes/ and use JSON (or JSONC, which allows comments and trailing commas). Each file describes one theme package that may contain multiple variants.
| Field | Required | Notes |
|---|---|---|
name |
Yes | Package identifier string |
description |
Yes | Plain string or i18n object {"default": "...", "zh_CN": "..."} |
themes[].id |
Yes | Globally unique install identifier |
themes[].name |
Yes | Plain string or i18n object |
themes[].css |
Yes | Path to CSS file in the theme source |
source.url |
Yes | Download URL for this version's archive. ${version} is replaced with the version field. |
source.sha256 |
Yes | SHA-256 checksum for integrity verification |
upgrade.policy |
Yes | github-release, git, http |
- Create a
.jsoncfile inthemes/following the format above - Run
python3 typora-theme-manager.py validateto check the file - Submit a PR
typora-theme-manager/
├── typora-theme-manager.py # Entry point
├── themes.schema.json # JSON Schema for validation
├── themes/ # Theme definition files
│ └── *.jsonc
└── src/
├── jsonc.py # Minimal JSONC decoder
├── typora_theme.py # Data model
├── upgrade_policy.py # Upgrade check policies
├── schema_validator.py # Schema validator
├── i18n/ # Translations
│ ├── en.jsonc
│ ├── zh_CN.jsonc
│ └── zh_TW.jsonc
└── commands/ # CLI commands
├── command.py
├── install.py
├── uninstall.py
├── list.py
├── upgrade.py
├── validate.py
└── help.py
MIT
{ // Package metadata "name": "typora-theme-phycat", "description": { "default": "A clean, elegant Typora theme family", "zh_CN": "一套简洁优雅的 Typora 主题", "zh_TW": "一套簡潔優雅的 Typora 主題" }, "author": "sumruler", "version": "v2.6.5", "license": "MIT", "license-url": "https://raw.githubusercontent.com/sumruler/typora-theme-phycat/refs/heads/main/LICENSE", "home-page": "https://sumruler.github.io/typora-theme-phycat", "source": { "url": "https://github.com/sumruler/typora-theme-phycat/archive/refs/tags/${version}.tar.gz", "sha256": "abc123def4567890abc123def4567890abc123def4567890abc123def4567890" }, // Theme variants — each has a globally unique `id` "themes": [ { "id": "phycats", // used in install/uninstall commands "name": { "default": "Phycat", "zh_CN": "Phycat", "zh_TW": "Phycat" }, "css": "phycats.css" // relative path to the CSS file } ], "fonts": [], "upgrade": { "check": "https://api.github.com/repos/sumruler/typora-theme-phycat/releases/latest", "policy": "github-release" } }