01Palette
10 main colors, plus 6 made from them.
| Swatch | Token | Hex | Role |
|---|---|---|---|
| Main | |||
| bg | #0D0F0C | Main background | |
| surface | #141713 | Secondary surfaces | |
| overlay | #1B1F1A | Elevated surfaces | |
| fg | #D7D9D2 | Normal foreground | |
| muted | #70766B | Muted text / comments | |
| moss | #7E9273 | Primary identity green | |
| forest | #536B4F | Deep green, receding roles | |
| olive | #9A9968 | Warm green for strings | |
| ochre | #B69A64 | Warm gold for values | |
| red | #A75D57 | Errors, destructive states | |
| Derived | |||
| border | #272C24 | Borders, dividers | |
| active | #191D18 | Cursor line / hover | |
| selection | #2A3527 | Selection background | |
| faint | #4B5147 | Disabled text, line numbers | |
| ochre-bright | #C7A46B | Strong warnings, escapes | |
| red-bright | #C06B63 | Strong errors, conflict | |
02Semantic Roles
Which color goes where.
| Role | Token |
|---|---|
| Text | |
| Normal text | fg |
| Secondary text | muted |
| Comments | muted |
| Disabled text | faint |
| UI | |
| Editor / main background | bg |
| Sidebar, titlebar, toolbar | surface |
| Panel, popup, menu, tooltip | overlay |
| Active tab | overlay |
| Inactive tab | bg |
| Borders, dividers | border |
| Cursor | moss |
| Selection | selection |
| Cursor line | active |
| Search match | selection + moss |
| Focus (ring / outline) | moss |
| Hover (rows, buttons) | active |
| Status bar | surface |
| Line numbers | faint |
| Active line number | moss |
| Diagnostics | |
| Error text | red-bright |
| Error icon, squiggle | red |
| Warning | ochre |
| Info | moss |
| Hint | muted |
| Git | |
| Added / untracked | moss |
| Modified | ochre |
| Deleted | red |
| Conflict | red-bright |
| Ignored | faint |
03Syntax Highlighting
Green for structure, warm colors for values, plain text for the rest. not final means it may change.
| Syntax | Token |
|---|---|
| keyword | moss |
| functionnot final | fg |
| methodnot final | fg |
| variable | fg |
| parameternot final | fg + italic |
| property / fieldnot final | fg |
| constant | ochre |
| string / char | olive |
| number | ochre |
| boolean | ochre |
| typenot final | fg |
| classnot final | fg + bold ok |
| module / namespace | fg |
| operator | forest |
| punctuation | muted |
| tag (HTML/XML) | forest |
| attribute | moss |
| decorator / annotation | ochre |
| comment | muted |
| doc commentnot final | muted + italic |
| escape sequence | ochre-bright |
| regex | ochre |
| special / builtin values | ochre |
| error-raising constructs | red |
//! Sample code to show the colors.
use std::collections::HashMap;
const MAX_DEPTH: usize = 64;
/// Tokenizes a source string into a flat list of tokens.
pub fn tokenize(input: &str) -> Result<Vec<Token>, ParseError> {
let mut tokens: Vec<Token> = Vec::new();
let mut depth: usize = 0;
let keep_eol = false;
for ch in input.chars() {
match ch {
'(' => depth += 1,
')' => depth = depth.saturating_sub(1),
'\n' if keep_eol => tokens.push(Token::Eol),
_ if ch.is_whitespace() => {}
_ => tokens.push(Token::Char(ch)),
}
if depth > MAX_DEPTH {
panic!("tree too deep");
}
}
let balanced = depth == 0;
if !balanced {
return Err(ParseError::Unbalanced { depth, line: 1 });
}
Ok(tokens)
}
04UI & Editor States
How it looks in the editor.
05Terminal & ANSI Slots
The 16 terminal colors.
- Bright colors are a bit lighter, not more saturated.
- No pure black, no pure white.
06Contrast
Contrast ratios against the background. Some colors are low on purpose, so they stay quiet.
| Token | on bg | on surface | Used for |
|---|---|---|---|
| fg | 13.5AA | 12.7 | normal text |
| ochre-bright | 8.2AA | 7.7 | strong warnings |
| ochre | 7.1AA | 6.7 | numbers, warnings |
| olive | 6.5AA | 6.1 | strings |
| moss | 5.7AA | 5.4 | keywords, accents, cursor |
| red-bright | 5.1AA | 4.8 | error text, critical errors |
| muted | 4.1below | 3.9 | comments, secondary text |
| red | 4.0below | 3.7 | error icons, squiggles |
| forest | 3.3below | 3.1 | operators, tags, decoration |
| faint | 2.4below | 2.2 | disabled, line numbers |
| border / active / selection | 1.1–1.5 | — | backgrounds, borders |
Selected text: fg on selection is 9.0:1.
07Ports
Ready-to-use themes, built from the spec. Download the file, or clone the repository and symlink it so a git pull updates the theme.
| App | File | Notes |
|---|---|---|
| Ghostty | ghostty/MOSS | deviation log inside the file |
| Zed | zed/moss.json | deviation log in zed/README.md |
| Claude Code | claude-code/moss.json | UI colors only; deviation log in claude-code/README.md |
| Pi | pi/moss.json | role mapping in pi/README.md |
| OpenCode | opencode/moss.json | role mapping in opencode/README.md |
| ZenNotes | zennotes/theme.css · zennotes/manifest.json | token mapping in zennotes/README.md |
| Slack | slack/theme.txt | slot mapping in slack/README.md |
| ZapFast | zapfast/moss.json | token mapping in zapfast/README.md |
| T3 Code | t3code/moss.json | UI colors only; deviation log in t3code/README.md |
| Any other app | tokens/moss.json · tokens/moss.css | the palette as data, for writing a new port |
git clone https://github.com/gentilfp/moss_theme.git ~/Developer/moss_theme
mkdir -p ~/.config/ghostty/themes
ln -sf ~/Developer/moss_theme/ghostty/MOSS ~/.config/ghostty/themes/MOSS
# then add to ~/.config/ghostty/config
theme = MOSS
Reload with cmd+shift+, or restart Ghostty.
mkdir -p ~/.config/zed/themes
ln -sf ~/Developer/moss_theme/zed/moss.json ~/.config/zed/themes/moss.json
Pick MOSS in the theme selector (cmd-k cmd-t), or set "theme": { "mode": "dark", "dark": "MOSS", "light": "MOSS" } in ~/.config/zed/settings.json.
mkdir -p ~/.claude/themes
ln -sf ~/Developer/moss_theme/claude-code/moss.json ~/.claude/themes/moss.json
Pick MOSS in /theme, or set "theme": "custom:moss" in ~/.claude/settings.json.
mkdir -p ~/.pi/agent/themes
ln -sf ~/Developer/moss_theme/pi/moss.json ~/.pi/agent/themes/moss.json
Pick MOSS in /settings → Theme, or set "theme": "MOSS" in ~/.pi/agent/settings.json.
mkdir -p ~/.config/opencode/themes
ln -sf ~/Developer/moss_theme/opencode/moss.json ~/.config/opencode/themes/moss.json
Pick moss with /theme, or set "theme": "moss" in tui.json.
mkdir -p ~/.config/zennotes/themes/moss
cp ~/Developer/moss_theme/zennotes/manifest.json ~/.config/zennotes/themes/moss/
cp ~/Developer/moss_theme/zennotes/theme.css ~/.config/zennotes/themes/moss/
Copy, do not symlink: ZenNotes skips a symlinked theme folder. Pick MOSS under Settings → Appearance → Custom. Run the cp commands again after a git pull.
#141713, #2A3527, #7E9273, #B69A64
Open Preferences → Themes → Custom theme → Import, paste the string and click Apply. Slack adapts the colors to keep contrast, so they may shift slightly.
THEMES="$HOME/Library/Application Support/me.paolino.zapfast/themes"
mkdir -p "$THEMES"
ln -sf ~/Developer/moss_theme/zapfast/moss.json "$THEMES/moss.json"
zapfast reload-themes
Pick Moss under Settings → Appearance, or use Open themes folder there. On Linux the themes folder is ~/.config/zapfast/themes/, and ZapFast notices changes there by itself.
In Settings → Appearance choose Add a theme, then Choose files and pick t3code/moss.json — or paste the file's contents into the Theme JSON box. Pick MOSS. T3 Code keeps imported themes in its own library, so import the file again after a git pull.
Neovim, VS Code and other apps are coming later.