Look words up from your terminal, using the same MDX dictionary files that GUI
apps like Eudic (欧路词典), GoldenDict, and MDict use.
No daemon, no index build, no GUI — type dic <word>, get a formatted entry in
about 100 ms.
Dictionary apps that read MDX files are almost all GUI programs. If you live in
a terminal, looking up a word means reaching for the mouse or switching apps.
Eudic on macOS, for instance, exposes no scripting interface that returns
results — its eudic:// URL scheme can only pop open the GUI window.
But Eudic (and friends) store their dictionaries as ordinary .mdx files on
disk. dic reads those files directly: it parses the MDX keyword table in
memory, seeks straight to the one compressed record block that holds your word,
and renders the entry's HTML as styled terminal text. The whole cold lookup —
including Python startup — takes ~100 ms, so no cache or background process is
needed.
- Fast: ~100 ms per lookup against a 162 MB dictionary, cold
- Pretty: headword, IPA, part of speech, numbered senses, grammar/register labels, and indented examples, colorized via rich
- Forgiving: case-insensitive fallback, follows
@@@LINK=alias redirects (with loop protection), and prints "did you mean" suggestions for typos - Scriptable: plain stdout, meaningful exit codes,
--htmlescape hatch - Any MDX file: point it at whatever dictionary you own via a flag or environment variable
- Editor-ready: ships with a Neovim plugin — look up the word under your cursor in a floating window (see Neovim plugin)
Requires Python ≥ 3.12 and uv (or pipx).
git clone https://github.com/SmartAI/dic-cli.git
cd dic-cli
uv tool install . # or: pipx install .If dic isn't found afterwards, run uv tool update-shell once and open a new
shell.
dic serendipity # look up a word
dic "bank holiday" # phrases work too (quote them)
dic --html serendipity # raw entry HTML (for debugging/piping)
dic --dict /path/to/other.mdx word # use a different dictionaryNot-found lookups print suggestions:
$ dic serendipzzz
dic: no entry for 'serendipzzz'; did you mean:
serenade
serendipity
serene
...
This repo doubles as a Neovim plugin (dic.nvim): press a key over any word
and its definition pops up in a floating window next to the cursor.
Requires Neovim ≥ 0.10 and the dic CLI on your $PATH
(see Install above). With lazy.nvim:
{
"SmartAI/dic-cli",
cmd = "Dic",
keys = {
{
"<leader>k",
function() require("dic").lookup() end,
mode = { "n", "v" },
desc = "Dictionary lookup",
},
},
}- the shortcut (or
:Dic) looks up the word under the cursor; in visual mode it looks up the selection, so phrases work too :Dic <word>looks up an arbitrary word- the float closes on cursor move,
q, or<Esc>; press the shortcut again to focus it and scroll long entries - not-found lookups show dic's "did you mean" suggestions in the float
Everything is optional, but the defaults can be tweaked via setup() (or
lazy.nvim's opts):
require("dic").setup({
cmd = "dic", -- or { "dic", "--dict", "/path/to/other.mdx" }
max_width = 80, -- float width cap, in columns
max_height = 0.6, -- float height cap, as a fraction of the screen
border = "rounded",
keymap = "<leader>k", -- alternative to the lazy.nvim `keys` spec above
})Exit codes: 0 found · 1 not found (suggestions on stderr) · 2
usage/config error — so you can script it:
dic "$1" || open "eudic://dic/#$1" # fall back to the Eudic GUI on a missdic finds the dictionary in this order:
--dict PATHflagDIC_MDX_PATHenvironment variable~/Library/Eudb_en/longman6.mdx— where Eudic on macOS keeps a user-imported LDOCE6
For a different default, set the environment variable in your shell profile:
export DIC_MDX_PATH="$HOME/dictionaries/my-dictionary.mdx"MDX is MDict's compressed dictionary format, long since reverse-engineered by
the community. Per lookup, dic:
- parses the MDX keyword section (word → byte offset) in memory via mdict-utils — cheap even for 50k+ headwords;
- resolves your query: exact match → case-insensitive match →
@@@LINK=redirects; - seeks into the file and zlib-decompresses only the record block containing the entry (never the whole file);
- parses the entry HTML with BeautifulSoup into structured senses and renders them with rich.
The HTML parser understands the markup of LDOCE6 (Longman Dictionary of
Contemporary English, 6th ed.). Other dictionaries still work end to end —
entries whose markup isn't recognized fall back to plain-text extraction, just
without the nice sense/example structure. Parsers for other popular
dictionaries are a welcome contribution: run dic --html <word> to inspect a
dictionary's markup, and see src/dic/parse.py for the LDOCE6 one.
uv sync
uv run pytestTests that need a real dictionary skip automatically when
~/Library/Eudb_en/longman6.mdx is absent. The parser tests use captured
entry HTML that is not distributed (dictionary content is copyrighted);
if you own LDOCE6, regenerate the fixtures as described in
tests/fixtures/README.md.
Design notes live in docs/superpowers/ — the original
spec and the step-by-step implementation plan.
This repository contains no dictionary content. dic is a reader for MDX
files you already own; obtaining dictionaries legally is your responsibility.
MIT © Min Liu