API docs: chrismaughan.com/Draxul β or generate locally with python scripts/gen_api_docs.py.
An experimental Dark Factory Agentic project with deep visualization of generated code.
- GPU-accelerated terminal host β cross-platform (Vulkan on Windows, Metal on macOS) terminal for PowerShell, WSL, Bash, Zsh, Git, and more
- Neovim GUI frontend β a full-featured replacement for nvim-qt, with deep
nvim --embedintegration over msgpack-RPC - Interactive city view of a codebase β a living 3D city where buildings represent code modules, with live performance and test coverage overlays, clickable links back to source. The city is a human metaphor for the code an agent is building: interactive, informative, and introspective. Richard Wettle tried this back in 2007; we are giving it another go! Here's his site: https://wettel.github.io/codecity.html
- High-end renderer β a cross-platform game engine-style rendering pipeline with ambient occlusion, shadow maps, anti-aliasing, HDR, and more
None of the code has been human-written. Draxul is 100% agentically coded using multiple agents on Claude, Codex, and Gemini. Code reviews, feature updates, and planning are managed by agents with a human arbiter. A part-time project, built in less than 3 weeks at time of writing β several person-years of equivalent effort.
Click any image to view full size.
For the full user-facing feature reference β config options, keybindings, terminal behaviour, mouse support, scrollback, and more β see FEATURES.md.
- Terminal emulator β run
zsh,bash,powershell, or any shell; cross-platform - Neovim GUI β full ext_linegrid UI with deep Neovim integration
- FreeType + HarfBuzz text pipeline with a dynamic glyph atlas
- Font fallback for Nerd Font, emoji, and plugin glyph coverage
- Configurable GUI shortcuts for the diagnostics panel, clipboard copy/paste, and font zoom
- Mouse input support for click, drag, and wheel events
- HiDPI / Retina-aware rendering with correct DPI font scaling
- Shared logging with console/file fallback and category filtering
- Thin app layer with separate window, renderer, font, grid, and Neovim modules
- Built-in diagnostics panel (toggle with
F12) with live renderer, layout, and startup timing
- CMake 3.25+
- Visual Studio 2022
- Vulkan SDK with
glslc nvimonPATH(optional β required only for Neovim mode)
- CMake 3.25+
- Xcode Command Line Tools
nvimonPATH(optional β required only for Neovim mode)
All other dependencies are fetched automatically with CMake FetchContent.
Debug:
cmake --preset default
cmake --build build --config Debug --parallelRelease:
cmake --preset release
cmake --build build --config Release --parallelDebug:
cmake --preset mac-debug
cmake --build build --parallelRelease:
cmake --preset mac-release
cmake --build build --parallelWith no arguments, Draxul starts an embedded Neovim child process (nvim must be on PATH).
To run as a plain terminal instead, use --host:
.\build\Release\draxul.exe # Neovim (default)
.\build\Release\draxul.exe --host powershell # PowerShell terminal
.\build\Release\draxul.exe --host bash # Bash (WSL)
.\build\Release\draxul.exe --host megacity --source C:\dev\linux # MegaCity scan root override
.\build\Release\draxul.exe --console # allocate a debug console for log outputFor a Debug build, replace Release with Debug.
./build/draxul.app/Contents/MacOS/draxul # Neovim (default)
./build/draxul.app/Contents/MacOS/draxul --host zsh # Zsh terminal
./build/draxul.app/Contents/MacOS/draxul --host bash # Bash terminal
./build/draxul.app/Contents/MacOS/draxul --host megacity --source ~/dev/linux # MegaCity scan root overrideOr launch via Finder / open:
open ./build/draxul.appSupported --host values: nvim, zsh, bash, powershell / pwsh (Windows), wsl (Windows), megacity.
--source <path> overrides the MegaCity Tree-sitter scan root when launching --host megacity.
Draxul stores user settings in a config.toml file under the platform app-config directory.
Programming ligatures are enabled by default. Set enable_ligatures = false if you prefer raw per-character glyphs.
GUI-level shortcuts can be remapped under a [keybindings] table:
enable_ligatures = true
[keybindings]
toggle_diagnostics = "F12"
copy = "Ctrl+Shift+C"
paste = "Ctrl+Shift+V"
font_increase = "Ctrl+="
font_decrease = "Ctrl+-"
font_reset = "Ctrl+0"These bindings affect only Draxul-handled GUI actions. Normal Neovim input and keymaps still go through Neovim.
The root do.py script is the recommended entry point for common tasks:
./do.py run # build (if needed) and launch Draxul
./do.py smoke # build and run the startup smoke test
./do.py test # full test suite (unit tests + smoke + render snapshots)
./do.py basic # run basic-view render snapshot compare
./do.py cmdline # run cmdline-view render snapshot compare
./do.py unicode # run unicode-view render snapshot compare
./do.py panel # run panel-view render snapshot compare
./do.py renderall # run all four render snapshot compares
./do.py blessbasic # bless basic-view reference image
./do.py blesscmdline # bless cmdline-view reference image
./do.py blessunicode # bless unicode-view reference image
./do.py blesspanel # bless panel-view reference image
./do.py blessall # bless all four reference images
./do.py api # build local Doxygen API docs
./do.py docs # build all documentation artifacts
./do.py shot # regenerate the README hero screenshot
./do.py coverage # macOS: export build/coverage.lcov and refresh db/coverage.lcovOn Windows, use do <command> (via do.bat) instead of ./do.py.
do build relwithdebinfo # Windows: optimized build with PDB symbols
do run # Debug build + run (ninja on Windows, make on macOS)
do run release # Release build + run
do run relwithdebinfo # Windows: optimized build with PDB symbols
do run release --vs # Release build with VS generator (Windows)
do run --console # Attach a debug console (Windows)
do smoke # Smoke test
do test # Full test suiteThe repository includes lightweight native tests for grid logic, redraw parsing, input translation, RPC behavior, renderer state, and Unicode width conformance against headless Neovim.
Default is Debug:
scripts\run_tests.batOther modes:
scripts\run_tests.bat release
scripts\run_tests.bat both
scripts\run_tests.bat --reconfigureDefault is Debug:
./scripts/run_tests.shOther modes:
./scripts/run_tests.sh release
./scripts/run_tests.sh both
./scripts/run_tests.sh --reconfigureThe test scripts reuse the existing CMake cache when possible and only reconfigure when needed.
The CTest suite also includes:
- an app startup smoke test when
nvimis available onPATH - a render snapshot regression test when the platform reference image exists under
tests/render/reference/
Draxul can now run deterministic render-snapshot tests by capturing pixels directly from the renderer output instead of taking a desktop screenshot.
Example compare run:
.\build\Debug\draxul.exe --console --render-test D:\dev\draxul\tests\render\basic-view.tomlBless a new reference image:
.\build\Debug\draxul.exe --console --render-test D:\dev\draxul\tests\render\basic-view.toml --bless-render-testUpdate the documentation screenshot for the current platform:
python .\scripts\update_screenshot.pyNotes:
update_screenshot.pyuses the presentation-orientedtests/render/readme-hero.tomlscenario by default, so it captures your normal Neovim theme and statusline instead of the clean-u NONE --nopluginregression setup.- The deterministic render regression scenarios remain under
tests/render/and continue to use fixed startup settings for stable compare/bless behavior.
Behavior:
- the scenario fixes window size, font, and Neovim startup commands
- Draxul waits for redraw activity to settle
- the renderer reads back the presented frame
- output is compared against a platform-specific reference image
actual,diff, andreportartifacts are written undertests/render/out/
Reference images live under tests/render/reference/ with platform suffixes like basic-view.windows.bmp and basic-view.macos.bmp.
Current scenarios:
basic-view: line numbers, signcolumn, cursorline, and baseline text layoutcmdline-view: bottom-row command-line renderingunicode-view: graphemes, emoji, wide glyphs, and Nerd Font/plugin iconspanel-view: visible diagnostics panel layout and content
Draxul now uses a shared repo-local logger across the app, RPC/process layer, windowing, font stack, and renderers.
Environment controls:
$env:DRAXUL_LOG = "debug"
$env:DRAXUL_LOG_CATEGORIES = "app,rpc,font"
$env:DRAXUL_LOG_FILE = "logs\\draxul.log"Notes:
- Default level is
info. - Categories are comma-separated.
- GUI launches without a console will fall back to a log file automatically.
- The DPI diagnostics in the window layer are now
debug-only instead of always-on.
Press F12 to toggle the built-in diagnostics panel. This can be remapped via config.toml under [keybindings].
The panel is a bottom-aligned dockable window rendered at native physical-pixel resolution using the same font as the terminal. It exposes live runtime state across three tabs:
Window β window and terminal region dimensions, display DPI, cell size, and grid dimensions
Renderer β last frame time, rolling average frame time, dirty-cell count, and glyph atlas occupancy, count, and reset statistics
Startup β per-phase initialisation timing (Config, Window + Renderer, Font, ImGui, Host) and total wall-clock time
The panel does not intercept any keyboard input β the terminal remains fully interactive while it is visible.
draxul/
βββ app/ # App startup and main orchestration
βββ libs/
β βββ draxul-types/ # Shared POD types and event structs
β βββ draxul-window/ # Window abstraction and SDL implementation
β βββ draxul-renderer/ # Public renderer API and platform backends
β βββ draxul-font/ # Font loading, shaping, glyph cache
β βββ draxul-grid/ # Cell grid and highlight state
β βββ draxul-nvim/ # Neovim process, RPC, redraw handling, input
βββ shaders/ # Vulkan and Metal shader sources
βββ fonts/ # Bundled font assets copied next to the app
βββ tests/ # Native test executable and fixture helpers
βββ scripts/ # Build/test convenience scripts
For a guided human-facing overview of the repo structure, generated diagrams, and validation entry points, see docs/module-map.md.
GitHub Actions builds and tests the project on:
- Windows
- macOS
The workflow uses the same repo-local test scripts as local development, including the startup smoke test.
- Windows uses a multi-config Visual Studio generator through
CMakePresets.json. - The renderer boundary is owned by
draxul-renderer; app code should not include backend-private headers. - Grapheme handling is much better than the original single-codepoint path, but broad Unicode width conformance against Neovim is still future hardening work.
- Visual regression testing now prefers direct swapchain/drawable readback over desktop screenshots so comparisons stay deterministic across window-manager state.
Regenerate with the prompt in plans/prompts/architecture_diagram.md.
Regenerate with python scripts/build_docs.py.
The live API reference is published automatically to chrismaughan.com/draxul on every push to main.
To generate locally:
python scripts/gen_api_docs.pyThis writes a local Doxygen site to docs/api/index.html.
Reference image:
What the render smoke does:
- launches a deterministic Neovim UI scenario at a fixed size with fixed fonts and commands
- waits for redraw activity to settle instead of capturing a half-initialized frame
- reads pixels back from the renderer output directly, not from the desktop compositor
- compares the captured image against a blessed platform reference
- writes
actual,diff, andreportartifacts undertests/render/out/
Why this is useful:
- it catches visual regressions that ordinary unit tests miss, such as tofu, broken fallback fonts, missing line numbers, layout shifts, or highlight mistakes
- the
diffartifact makes it obvious what changed and roughly how much changed - the
reportgives a mechanical pass/fail threshold instead of relying on guesswork --bless-render-testgives a controlled way to accept intentional visual changes
















