A metallurgy-inspired colorscheme for Neovim inspired by the colors of the Rust programming language and the chemistry of iron oxidation. Ships with paired dark and light palettes.
📸 Click to View Screenshots
Each image is split diagonally — light theme in the upper-left half, dark theme in the lower-right half.
Ferric draws from the forge — iron oxide, copper patina, heated metal, and cobalt. The result is a theme that feels industrial, precise, and alive — like staring into a blacksmith's workshop where every tool glows at a different temperature.
The name comes from ferric (Fe³⁺) — iron in its oxidized state. Rust.
Ferric treats color as a tool, not decoration. It follows the argument in Nikita Prokopov's "I am sorry, but everyone is getting syntax highlighting wrong": if everything is highlighted, nothing stands out.
- Highlight what you read for — comments, strings, numbers, constants, and function/type definitions. These are the landmarks you scan for.
- Dim the machinery — keywords (
if,for,let,pub,mut), function calls, variables, and punctuation fall back to plain text. Most code is these; coloring them is noise. - Reserve color for meaning — red means errors only; magenta flags
hazards — code the language marks as handle-with-care, like Rust's
unsafe. Each rare color carries a single, unambiguous meaning. - Hold the UI to the same standard — the current line number, the selected completion/picker item, diagnostics, and the active mode stand out; relative line numbers, inactive windows, and decorative chrome recede.
The payoff is calm code where the handful of things that matter genuinely pop.
Highlighting is driven by Treesitter captures and LSP semantic tokens
(with classic syntax groups as a fallback), so these rules apply to any
language with a parser or language server — the definition-vs-call distinction,
primitives, dimmed keywords, and macros all work the same in, e.g., C via
clangd as in Rust via rust-analyzer. The lone language-specific accent today
is the hazard color (magenta): it currently lights up Rust's unsafe, and
is reserved for any equivalent "handle with care" construct other languages
expose.
| Role | Dark | Light |
|---|---|---|
| Error | #cf4238 |
#8a0000 |
| Warning | #c7ab35 |
#896d00 |
| Info | #5290d3 |
#1e5d9c |
| Hint | #2ea3a9 |
#007379 |
| Ok | #50b27a |
#007c48 |
| Role | Dark | Light |
|---|---|---|
| Added | #50b27a |
#007c48 |
| Changed | #c7ab35 |
#896d00 |
| Deleted | #d45443 |
#9c1b10 |
| Diff add bg | #204838 |
#d4ecdc |
| Diff change bg | #1a3838 |
#cce4e0 |
| Diff delete bg | #5a2020 |
#fcd4c8 |
{
"freddiehaddad/ferric.nvim",
lazy = false,
priority = 1000,
config = function()
vim.cmd.colorscheme("ferric")
end,
}vim.pack.add({ "https://github.com/freddiehaddad/ferric.nvim" })
-- vim.cmd.background("light")
vim.cmd.colorscheme("ferric")Clone this repository into your Neovim packages directory:
git clone https://github.com/freddiehaddad/ferric.nvim \
~/.local/share/nvim/site/pack/plugins/start/ferric.nvimThen add to your config:
vim.cmd.colorscheme("ferric")Ferric can be configured before loading the colorscheme. The defaults are:
require("ferric").setup({
terminal_colors = true,
palette_overrides = {},
overrides = {},
})
vim.cmd.colorscheme("ferric")Ferric selects its palette from vim.o.background. Set it before
(or alongside) :colorscheme to pick a mode:
vim.o.background = "light" -- or "dark" (default)
vim.cmd.colorscheme("ferric")palette_overrides are applied on top of whichever palette is active and
follow you across mode switches.
To track your system or terminal preference, re-source the colorscheme
whenever background changes:
vim.api.nvim_create_autocmd("OptionSet", {
pattern = "background",
callback = function()
if vim.g.colors_name == "ferric" then
vim.cmd.colorscheme("ferric")
end
end,
})The palette tables themselves are exposed under ferric.palettes:
local dark = require("ferric.palettes.dark")
local light = require("ferric.palettes.light")Pair with Comic Code monospaced font for the full aesthetic or one of the free alternatives: