AnaNeo is a fork of ReNeo by Rojetto and qwertfisch. Most of the code originates from ReNeo and is licensed under GPL-3.0, as before. AnaNeo is a private project made public β see About this fork before you rely on it.
π The wiki documents all 21 layers β one page per themed block, with a picture of every layer β and the complete configuration space.
AnaNeo implements the Neo keyboard layout and its relatives on Windows. There are two main modes of operation:
- standalone mode: AnaNeo replaces all key events of the native layout (likely QWERTZ or QWERTY) with the desired Neo layout. You only need to run the AnaNeo executable on system startup.
- extension mode: First, install a native Neo driver like kbdneo. AnaNeo then supplements all functions that can't be implemented in the native driver (capslock, navigation keys on layer 4, compose, ...).
AnaNeo is not a competitor to ReNeo, it is one layout taken further. ReNeo carries the whole Neo family and stays close to the published standards; AnaNeo keeps four of those layouts β Neo, NeoQwertz, Noted and AnNoted (Bone, AdNW, Mine, KOY, VOU and 3l were dropped) β and puts the work into AnNoted, its own variant of Noted.
- Refreshing Noted. AnNoted keeps Noted's letter arrangement and its native driver (
kbdnoted.dll), but is free to depart from the published standard where an extension has a reason to. Noted itself stays in the package unchanged as a standard-conform standalone layout, so nothing is taken away. - More layers. AnNoted has 21 layers instead of 6: layers 1 to 4 as usual, then five themed blocks β maths, typography, Ancient Greek, Cyrillic, extra β and layer 21 for the compose modifiers. No physical key carries the block modifiers; a block is reached by locking it, which is why the lock model had to become a first-class part of the program rather than a switch for layer 4.
- Systematising the functionality. Any set of modifiers can be locked, and a lock is described in
config.jsoninstead of being hard-coded. The compose tree follows a stated grammar β the layer carries the grip, the tree carries the derivation β and two of the compose modules (font variants, enclosed characters) are generated from code rather than maintained by hand, with tests holding file and calculation together. A separate command-line build,ananeo-tool, reports on the compose stock: origin, coverage, gaps, duplicates, and which layer each continuation sits on. - The display was rebuilt, not invented. The on-screen keyboard comes from ReNeo. What it shows is now computed in a separate, testable module; it renders glyphs through the font's own
cmaptable, so characters beyond the Basic Multilingual Plane (chess, alchemy, Mathematical Alphanumeric Symbols) appear instead of empty boxes; it carries a layer strip and a live preview of the running compose sequence. New alongside it is a printable, self-contained HTML layout sheet.
Unchanged from ReNeo is the part that is hardest to get right and easiest to break: the low-level keyboard hook, the modifier bookkeeping and the forced modifier state. That work is Rojetto's and qwertfisch's, and it is why this fork could concentrate on layouts and compose.
AnaNeo is vibe-coded. Almost all of the code, tests and documentation added in this fork were written by Claude (Anthropic's Claude Code agent) under human direction. Decisions, reviews and the manual acceptance testing are the human side of it: anything that touches the keyboard hook, the modifier state or the drawing cannot be proven by a unit test and has to be tried on a real Windows machine. Each development round therefore ends with a written acceptance protocol.
Two consequences worth knowing before you install it:
- The automated test suite is large and covers the pure data and logic modules β layout parsing, layer and lock logic, the compose tree, the key descriptions, the font
cmapreader, the report generators. It does not cover the hook, the sending of key events, or the drawing itself. - Development happened in a private working copy. The project log, the specifications and plans, and the acceptance protocols are German-language working documents and are not part of this repository β this README and
README_DE.mdare the parts written for readers from outside.
- optional: Install kbdneo normally
- Download newest release and unpack in a directory with write permissions, e.g.
C:\Users\[USER]\AnaNeo - Start
ananeo.exeoder add it to the autostart list. Use the tray icon to deactivate or quit the program. - optional: Tweak
config.json(generated on first start)
Update
Download new release and overwrite existing files with package contents. Because config.json isn't contained in the release package user settings are preserved.
Uninstallation
- optional: Uninstall kbdneo according to Neo wiki tutorial
- Delete AnaNeo directory and remove executable from autostart
-
Supports the layouts Neo, NeoQwertz, Noted and AnNoted, switchable from the tray menu. AnNoted is Noted's own variant; in extension mode against
kbdnoted.dllit is the active one, while Noted itself is selectable in standalone mode only. -
Lockable layers: Capslock (both Shift keys), mod 3 lock, mod 4 lock, and any further lock you configure via
"locks"inconfig.json.M3+Escreleases everything. While a layer is locked the tray icon changes colour and its tooltip names the lock. -
Themed layers: beyond layers 1 to 4, AnNoted has five themed blocks and a modifier layer β 21 in all. Each block has its own modifier (Mod5 to Mod9); since no physical key carries those, a block is entered by locking it, and holding Shift, Mod3 or Mod4 then reaches its other layers.
Layers Trigger Block 1β4 β / Shift / Mod3 / Mod4 as usual 5β8 M3+F2/ +Shift / +Mod3 / +Mod4maths and logic (7 = superscript, 8 = subscript) 9β12 M3+F3/ +Shift / +Mod3 / +Mod4typography 13β14 M3+F4/ +ShiftAncient Greek, lower/upper case 15β16 M3+F5/ +ShiftCyrillic (Russian) 17β20 M3+F6/ +Shift / +Mod3 / +Mod4extra: symbols, emoji (19), dice and alchemy (20) 21 hold Mod3+Mod4the six compose modifiers, reachable from every lock state Only AnNoted has these layers β Neo, NeoQwertz and Noted stay at their six published ones. The space bar carries its own hierarchy of ever narrower spaces on layers 3 to 7.
π The wiki documents every layer, one page per block, with a picture of each.
-
On-screen keyboard, via the tray menu or
M3+F1. Follows the modifiers as you press them, names the current layer and block while one is locked, and previews a running compose sequence. Draws characters beyond the Basic Multilingual Plane correctly β chess, alchemy, Mathematical Alphanumeric Symbols β using a bundled symbol font (Noto Sans Symbols 2, infonts/, SIL Open Font License 1.1) loaded privately into the process without installing it. Five colour schemes;Sachlichis the default and follows the Windows light/dark setting. See the wiki. -
All dead keys and compose sequences, extensible by users:
composeModulesinconfig.jsondecides which files fromcompose/load, and in which order. AnaNeo adds its own grammar on top β superscript, subscript, enclosed characters and 1021 font variants, derived rather than stored. See the wiki.- Unicode input:
β«uu[code point in hex]<space>, e.g.β«uu1f574<space>β π΄ - Roman numerals:
β«rn[number]<space>lower case,β«RN[number]<space>upper case, 1 to 3999.β«rn1970<space>β β Ώβ ½β Ώβ Όβ Ήβ Ή - Sticky modifiers keep a sequence open:
Λ£ 1 2 3gives ΒΉΒ²Β³
- Unicode input:
-
Shift+Pausede(activates) the program. -
One-handed mode: while enabled and the mirror key (space by default) is held, the keyboard is mirrored. Tray menu or
M3+F10. -
Layouts can be added and modified in
layouts.json.
As an extension to the native driver:
- Navigation keys on layer 4
- If the native layout is recognized as Neo-related (
kbdneo2.dll,kbdgr2.dll,kbdnoted.dll), AnaNeo automatically switches to extension mode. Switching between layouts is possible as normal. - Improved compatibility with Qt and GTK applications. Workaround for this bug.
- Compose key
M3+Tabdoes not send tab character to applications. Workaround for this bug.
A printable, self-contained HTML sheet of the current key assignment β one keyboard, one tab per layer, and all layers stacked below each other when printed. Two ways to get one: the tray menu entry "Create layout sheet" shows what the running program has loaded, and ananeo-tool sheet [layout name] generates it from the files on disk without a running AnaNeo.
An accent bar marks a key that produces a character, with its code point below; dimmed keys are function keys, filled ones are modifiers, and dashed outlines are unassigned positions. The wiki explains it in full.
Two files, both next to the executable: config.json holds your settings and is created on first start, layouts.json holds the layouts themselves. Neither needs a rebuild β edit and restart AnaNeo.
The full reference lives in the wiki, with the reasoning and the pitfalls:
| Wiki page | Covers |
|---|---|
| Configuration | how your settings and the defaults are merged, and the top-level options |
| Locks and triggers | locks β which modifiers lock, by which chord, and the fixed actions |
| On-screen keyboard | osk β theme, ISO/ANSI, numpad, number row, modifier names |
| Compose modules | composeModules, compose β which sequence files load, in what order |
| Hotkeys and blacklist | hotkeys, blacklist |
| One-handed mode | oneHandedMode β mirror key and mirror map |
| Editing layouts | layouts.json β layers, keys, keysyms, forced modifiers |
| Option | Values | Meaning |
|---|---|---|
standaloneMode |
true (default) / false |
replace the native layout, or only supplement a Neo driver and deactivate otherwise |
standaloneLayout |
"AnNoted", "Noted", "Neo", "NeoQwertz" |
layout for standalone mode; also in the tray menu |
language |
"german" / "english" |
program language |
filterNeoModifiers |
true (default) / false |
hide M3/M4 events from other programs in extension mode (bug); false if you want to bind them in an application |
autoNumlock |
true (default) / false |
switch Numlock on automatically; false for laptops whose numpad sits on the letter keys |
blacklist |
list of {"windowTitle": "β¦"} |
deactivate AnaNeo for windows whose title matches the regex |
composeModules |
list of file names without extension | which files from compose/ load, in this order |
compose.oskAutoShow |
false (default) / true |
open the on-screen keyboard while a compose sequence runs |
locks.oskAutoShow |
false (default) / true |
open the on-screen keyboard while a layer is locked |
locks.triggers |
list of {"chord": β¦, "lock"/"action": β¦} |
which chord locks what, or performs a fixed action |
osk.theme |
"Sachlich" (default), "Grey", "NeoBlue", "ColorClassic", "ColorGreen" |
colour scheme; Sachlich follows the Windows light/dark setting |
osk.layout |
"iso" / "ansi" |
physical keyboard shape |
osk.numpad, osk.numberRow |
true / false |
show the numeric keypad, show the number row |
osk.modifierNames |
"standard" / "three" |
label modifiers M3, M4 or Sym, Cur |
hotkeys.toggleActivation |
e.g. "Shift+Pause", or null |
global shortcut switching AnaNeo on and off |
hotkeys.toggleOSK, hotkeys.toggleOneHandedMode |
shortcut or null (default) |
already reachable as M3+F1 and M3+F10 |
oneHandedMode.mirrorKey |
scan code, "39" (space) by default |
key that mirrors the keyboard while held |
oneHandedMode.mirrorMap |
"original": "mirrored" scan codes |
which key becomes which; adjust for ergonomic and matrix keyboards |
configVersion |
number, maintained automatically | records which migration steps this config has seen |
Hotkey syntax: modifiers Shift, Ctrl, Alt, Win plus a main key from the VKEY enumeration in source/mapping.d, based on the Win32 virtual-key codes. null registers no global hotkey.
Lock trigger syntax: "chord" plus either "lock" or "action". The same modifier twice ("Shift+Shift") means left and right key together; otherwise all parts but the last are held modifiers. Lockable are Shift and Mod3 to Mod9 β not Ctrl or Alt, which would capture every application shortcut. Actions are "capslock", "clearLocks", "osk", "oneHandedMode" and "compose". Full grammar in the wiki.
Arrays are replaced whole when your settings are merged with the defaults, not merged field by field. If your config.json already has a "triggers" array, newly shipped triggers will not appear in it. Delete that entry β or the whole "locks" block β once and restart.
The same used to apply to "composeModules"; renamed and newly shipped modules are now carried over automatically. If something is missing anyway, deleting that entry once has the same effect.
layouts.json defines every layout: modifiers (scan code β modifier), layers (the modifier state each layer requires, tested in order), capslockableKeys, and map (scan code β one entry per layer). An entry carries a keysym plus either a char or a vk, optionally a label and forced mods.
Put your own changes in AnNoted β the other three layouts reproduce published standards. Adding a layer means adding an entry to every line of map.
The wiki page has the field reference, the procedure for creating a new layout, and the traps β empty cells becoming VK_VOID, invisible characters needing \uXXXX escapes, why a cell needs both keysym and char, and why you must never re-serialise the file with a JSON library.
As soon as several nested operatings systems interoperate things get difficult. Because different VM software and remote desktop clients behave differently there is no universal solution. What follows is some general advice and a few tested configurations.
For optimal compatibility, the innermost system should generally implement the alternative layout and all outer systems should be set to QWERTZ/QWERTY. In the case of virtual machines this means QWERTZ on the host and a Neo driver on the guest system. For remote desktop machines a local QWERTZ setup and a Neo driver on the remote system are recommended.
If it turns out that programs work better without AnaNeo, the offending programs can be added to the blacklist for AnaNeo to automatically deactivate, see configuration.
Set Windows to QWERTZ (without AnaNeo), then set the Neo layout in X11 using setxkbmap.
Set host to QWERTZ, then install Neo driver (e.g. AnaNeo) in guest system.
Use AnaNeo in standalone mode on the local system. Letters and (non-unicode) special characters are transmitted correctely to the remote system.
AnaNeo is written in D and uses dub for project configuration and compilation.
There are three build settings:
- Debug with
dub build: In addition to debugging symbols, the generated executable opens instantiates a console to output debugging imformation. - Debug and log with
dub build --build=debug-log: Similar to debug but console output is additionally written toananeo_log.txt. Caution: this log file may contain sensitive information! - Release with
dub build --build=release: Optimizations are active and no console is instantiated.
The resource file res/ananeo.res is built using rc.exe from the Windows SDK (x86 version, otherwise the generated res file won't work). The command ist rc.exe ananeo.rc.
Cairo DLL originates from https://github.com/preshing/cairo-windows. The D header files were generated from the C headers using DStep and manually tweaked.
A tag of the form v* triggers a GitHub action to generate a release draft. Based on the different config.[layout].json files, several pre-configured ZIP archives are created.
Uses Cairo licensed under the GNU Lesser General Public License (LGPL) version 2.1.
