`-dev-` was in every Emacs symbol this client owns and meant nothing to anyone typing one: the daemon is `flan dev` at a shell, but from inside Emacs there is no other kind of connection to distinguish it from. `M-x flan-dev` is now `M-x flan`, `flan-dev-quit` is `flan-quit`, the private prefix `flan-dev--` is `flan--`, and every defcustom follows — ninety-odd symbols, with the two files renamed to emacs/flan.el and emacs/test-flan.el so the file names say the same thing as the symbols in them. No aliases. Renaming a defcustom breaks a config that names it and there is no way around that; the repo has no precedent for softening one, and an alias left behind is what keeps a rename from finishing. MANUAL.md says the old names are gone and how to fix a config, which is the whole of the migration path. Three strings are not symbols and keep their spelling: `.flan-dev.sock`, which bin/main.ml writes and which a renamed variable searching for a renamed file would simply never find; and the two buffer names `*flan-dev*` and ` *flan-dev*`, which name the `flan dev` subcommand's own output rather than anything in elisp. `flan dev` with a space is the CLI and is untouched everywhere. The entry point also stops asking a question it already has the answer to. From a buffer visiting a .flan file it starts that file; from anywhere else it reads one from the minibuffer as before; `C-u` reads one either way, which is how you start a second program without leaving the first. The current buffer is still the only source of the default — the bug where a previous project won over the buffer you were in was fixed by removing `flan--file` from that position, and nothing here puts it back. Four checks on the `interactive' form, evaluated on its own rather than by calling the command, because calling it would build and launch a program and the question is only which file the form arrives at and whether it had to ask. A fifth asserts that nothing answers to the old names. test/test_emacs.ml loads the test file by path and test/test_session.ml names the client file in a comment, so the rename reaches those two lines; nothing else outside emacs/ and the docs moved. Verified by byte-compiling every file clean and by `dune test` and `@page`.
6.6 KiB
Reference clones on this machine
Read the source, do not recall it. Every claim in this repository's notes that came from one of these
was read out of the clone, and the ones that were recalled instead have been wrong before — see
NEXT.md's corrections. When a note cites a file and line, it is because someone opened it.
All paths are under ~/Repositories. Dates are the last commit in the clone at the time this file was
written (2026-09-13); a stale clone is still the right source for how a thing works, just not for what
its newest release does.
The ones this language is built against
| Clone | Last commit | What it answers |
|---|---|---|
Odin |
2026-07-10 | The primary reference. Memory model, containers, generics. |
sbcl |
2026-09-07 | Conditions and restarts — what they should mean. |
zig |
2026-09-12 | Comptime, build system, error handling, C interop. |
jank |
2026-09-11 | A Clojure with native interop and a REPL into a running process. |
janet |
2025-09-29 | A small embeddable Lisp. varfn and its reload story. |
raylib |
2026-07-16 | The C library the FFI binds. Note: vendor/raylib/raylib-5.5.h in this repo is the committed header the bindings are checked against on every build; the clone may be a different version. It used to be whatever vendor/raylib/web/ happened to hold, which is gitignored and therefore absent from a fresh worktree — the reason the header is tracked now. |
Odin, specifically
Most of what this repository copies. Places already cited in the notes:
base/runtime/core.odin:369—Map_Info. The type-erased container runtime:rawptrkeys, cell info for size and alignment, hash and equality as function pointers. This is whyVecandMaphere need no generics, and it is the thing that was not converted when generics landed —VecandMapare still type-erased, and a$tonly reaches them as an element or key type.base/runtime/dynamic_map_internal.odin— the map algorithm(Map K V)follows.base/runtime/dynamic_array_internal.odin— the same forVec.src/check_expr.cpp:470-510—find_or_generate_polymorphic_procedure. The instantiation cache: a polymorphic proc entity carries agen_procslist, each call builds the concrete proc type, and the checker scans forare_types_identicalbefore generating a newEntity. This is the machinery the generics spike copied.src/check_type.cpp:173-200—FieldFlag_usingandFieldFlag_subtype. Odin's answer to "a function over anything with these fields": nominal embedding, not row polymorphism.
Two Odin facts worth keeping together, because conflating them has already caused one wrong note:
$T procs are monomorphised, containers are type-erased. Odin uses both and picks per case.
Also present, same family
odin-examples, ols (the Odin language server), odin-imgui,
odin-raylib-hot-reload-game-template — the last is a worked hot-reload loop in the language this
one borrows its memory model from.
Lisp, conditions, and the editor loop
| Clone | Last commit | What it answers |
|---|---|---|
farolero |
2023-05-05 | Common Lisp conditions and restarts, portably — a smaller read than SBCL's for semantics. |
lem |
2025-08-29 | An editor written in CL. Its own REPL and process model. |
cider |
2026-09-10 | The Clojure editor protocol this repo's flan.el is shaped after. |
emacs |
2026-04-18 | Overlays, faces, pre-command-hook — the C and Lisp behind the editor half. |
fennel-ls |
2026-05-06 | A Lisp language server. |
Carp |
2026-08-24 | A statically typed Lisp with no GC. The closest thing to this language's premise. |
lisp |
— | assorted. |
cl-missile-command, b12n-raylib-clj, raylib-clojure-playground |
— | games in the Lisps, the same corpus ~/Development/fnm ports. |
Carp deserves the note it has: statically typed, no GC, Lisp syntax, borrow-checked. Whatever it
got right or wrong is the nearest prior art to what is being built here.
Compiling to JavaScript
Cloned 2026-09-17, for the JS backend (FIX.org item 6, docs/DISCUSS.md §5).
| Clone | What it answers |
|---|---|
Fable |
The best semantic match: statically typed F# to readable JS, value-semantics structs, real i64/u64. src/fable-library-ts/Long.ts, Int32.ts, BigInt.ts for how .NET integer semantics live on JS numbers; src/Fable.Transforms/ for how a typed AST lowers, including where structs get cloned at assignment and call sites. Large — read it for specific answers, not through. |
squint |
A small Clojure-syntax-to-JS compiler. src/squint/compiler.cljc is the emitter to read for output style and structure. |
clojurescript |
The full-size version of the same problem, including host interop. Consult, don't read through. |
The Lisp-to-JS pair never faces the two hard questions here — integer width and struct copy semantics — because they are dynamic. Fable does, which is why it is on this list despite being neither a Lisp nor small.
Graphics and the C boundary
raylib, raygui, glfw, SDL, freetype-gl, TIC-80, aseprite, macroquad, godot, bevy.
glfw and SDL matter for the window and input layer raylib sits on. TIC-80 and aseprite are
real C/C++ programs to read for how they structure a frame loop.
Tooling, debuggers, terminals
tree-sitter (grammars — relevant if the editor mode ever stops being regexp-based), dape (a
debug-adapter client for Emacs), gf (a GDB frontend), kitty, st, ratatui, stumpwm.
dape and gf are the two to read when the debugger question comes back: this repo emits DWARF
already and flan dev --debug exists.
Everything else
Ambient, CelesteClone, RI-DASH, RichTextFX, controlsfx, openglfx, cljfx, pyimgui,
emsdk (the Emscripten SDK — the web target uses it), esp-idf, linux, fedora-kernel,
quickemu, OSX-KVM, tauri, keyd, alttab, xdg-ninja, jpm, cl-git, bragi, calm,
pretty, dash-*, graph-rag, gptel, neocaml, marian, brainfuck,
minimal_blockchain_in_rust, mpgameserver, computer_enhance, interactive-c-demo,
falconerd-editor, unity-paper.io-2, vscode-defold, PyPaperBot, RyzenAdj, Tug,
doom-themes, odin-webgl-experiment.
emsdk is the only one of these on a build path — the --target=web build needs it.
Related, not under ~/Repositories
~/Development/fnm — the author's own falling-sand and siam-farmer ports in Clojure, Common Lisp,
jank, Janet, Odin, OCaml and JS. PORTING.md in this repository is the report written from reading
them, and sand.flan is kept at parity with lisp/sand.lisp, clojure/src/fnm/sand.clj and
src/fnm/sand.jank.