The Problem

Researchers and writers who work in markdown need a tool that links notes, manages a knowledge graph, and supports vim-style editing without leaving the terminal. Obsidian does this in a GUI; Ekphos brings the same workflow to a TUI with a fraction of the resource footprint.

What This Does

Ekphos is a Rust terminal application that renders markdown notes with an internal wiki-link graph, inline image support (iTerm2/Kitty/WezTerm/Sixel), vim modal editing, and themeable UI. The codebase is organized into src/app/ (application state), src/editor/ (buffer, cursor, history, wrapping), src/event/ (input handling), src/ui/ (rendering: sidebar, outline, graph view, status bar), and src/vim/ (motions, operators, text objects, registers, macros, marks).

The README documents install via cargo install ekphos; a Makefile, Dockerfile, and docker-compose.yml exist for alternate builds.

How It Is Wired

Execution starts at main in src/main.rs:103, which reaches 356 functions. From there control flows into run_app and process_events in src/event/handler.rs, which dispatches to vim-mode handlers (handle_vim_normal_mode, handle_vim_visual_mode) and edit-mode handlers. The vim handlers route through move_cursor and reset_pending heavily — handle_vim_normal_mode -> reset_pending is called 56 times, -> move_cursor 39 times.

The widest blast radius sits in src/app/state.rs (167 functions, 29 types, called from 9 files): is_empty is called from 97 places, find_bounds from 56. src/editor/buffer.rs is the most depended-upon module (called from 17 files) via line_count, is_empty, gap_pos. src/vim/text_object.rs owns find_bounds and word-boundary logic. src/event/handler.rs is the largest file at ~3,600 lines and holds execute_motion_or_operator (55 functions reachable) and execute_text_object (37 reachable).

The dependency graph has no circular modules. The cost of the current layout is that handler.rs and state.rs are oversized — a change in either ripples widely, and the 10-level nesting makes control flow hard to follow.

How To Use It

git clone https://github.com/moses-y/ekphos
cd ekphos
make run        # or: cargo run

Configuration lives in user config (the README mentions ekphos --reset to reset it). Themes are in themes/ as TOML files (dracula.toml, ekphos-dawn.toml). Requires Rust 1.70+; image rendering needs a compatible terminal.

Code Health & Issues

Static analysis (not opinion) found 22 findings: 9 high, 13 medium. Three kinds:

  • High – deep nesting (15 instances): max indentation depth 10 in src/app/state.rs, src/editor/mod.rs, src/event/handler.rs. Flatten with early returns.
  • High – duplicated code (32 repeated 6-line blocks across 11 files): extract shared helpers.
  • High – oversized files (6): src/app/state.rs at ~3,600 lines; split by responsibility.

SDLC gaps: no test files, no CI configuration, and the Dockerfile uses mutable base images (rust:slim, debian:trixie-slim) with no USER directive — pin by digest and add an unprivileged user. No secrets committed; license and lockfile present.

The Bottom Line

A capable vim-first markdown research tool with a sensible module split, but the event handler and state files need decomposition before they become unmaintainable. The missing test suite and CI are the real blockers for anyone planning to extend it. Suitable for terminal-native researchers who already live in vim keybindings.