No description
  • Scheme 90.7%
  • C++ 3.6%
  • C 2.9%
  • Makefile 1.2%
  • Shell 1.1%
  • Other 0.5%
Find a file
Jaime Fournier 306a96ac70
Some checks are pending
CI / build-test-audit (push) Waiting to run
Security Baseline / baseline (push) Waiting to run
Restore LSP request timeouts
2026-07-30 17:22:11 -06:00
.github/workflows Use Jerboa 0.2.8 toolchain 2026-07-30 14:07:04 -06:00
.jerboa Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
docs Use Jerboa 0.2.8 toolchain 2026-07-30 14:07:04 -06:00
scripts Audit Qt echo-only parity commands 2026-07-30 16:31:23 -06:00
src Restore LSP request timeouts 2026-07-30 17:22:11 -06:00
support Stop patching vendored jerboa-shell 2026-07-30 16:24:09 -06:00
tests Restore LSP request timeouts 2026-07-30 17:22:11 -06:00
tools pre-commit: build + test before allowing commit 2026-04-29 15:04:50 -06:00
.build.yml Use Jerboa 0.2.8 toolchain 2026-07-30 14:07:04 -06:00
.containerignore Use Podman for container builds 2026-07-30 13:51:41 -06:00
.gitignore docs: update AGENTS.md with ~/.local/bin/jerboa path; ignore generated vendor-overrides .ss 2026-07-24 12:37:45 -06:00
.jerbuild Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
.jerbuild.freebsd-amd64 Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
.jerbuild.linux-amd64 Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
.jerbuild.linux-arm64 Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
.mcp.json updates 2026-03-28 20:00:00 -06:00
AGENTS.md Use Podman for container builds 2026-07-30 13:51:41 -06:00
build-binary-qt.ss Use Podman for container builds 2026-07-30 13:51:41 -06:00
build-binary.ss Security hardening and release readiness 2026-06-23 10:52:52 -06:00
CLAUDE.md Keep vendor as build-time checkouts 2026-06-14 17:31:11 -06:00
Containerfile Use Podman for container builds 2026-07-30 13:51:41 -06:00
Containerfile.qt Use Podman for container builds 2026-07-30 13:51:41 -06:00
Containerfile.tui Use Podman for container builds 2026-07-30 13:51:41 -06:00
dependencies.lock Add Qt mouse press handling 2026-07-30 14:58:55 -06:00
emacsclient.ss Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
jemacs-main.c Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
jemacs-qt-main.c Security hardening and release readiness 2026-06-23 10:52:52 -06:00
jemacs-ssh-agent-stub.c Update chez-* vendor refs to jerboa-* (qt, scintilla, ssl, https, pcre2, ssh, sqlite, crypto, fuse) 2026-05-28 11:05:35 -06:00
jemacs-tls-stubs.c Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
jpkg.policy.sexp Add jpkg package CI 2026-06-18 16:32:16 -06:00
jpkg.sexp Add jpkg package CI 2026-06-18 16:32:16 -06:00
LICENSE Security hardening and release readiness 2026-06-23 10:52:52 -06:00
main.ss Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
Makefile Stop patching vendored jerboa-shell 2026-07-30 16:24:09 -06:00
plan-android.md Use Jerboa 0.2.8 toolchain 2026-07-30 14:07:04 -06:00
plan.md Drop all gerbil references — zero in repo now 2026-05-28 13:23:35 -06:00
qt-main.ss Security hardening and release readiness 2026-06-23 10:52:52 -06:00
README.md Use Podman for container builds 2026-07-30 13:51:41 -06:00
SECURITY.md Harden IPC, REPL, and dependency provenance 2026-07-11 17:22:04 -06:00
todo.md Update chez-* vendor refs to jerboa-* (qt, scintilla, ssl, https, pcre2, ssh, sqlite, crypto, fuse) 2026-05-28 11:05:35 -06:00

jerboa-emacs

A Chez Scheme port of the jerboa-based Emacs-like text editor, featuring a TUI (terminal) backend and a Qt graphical frontend.

Overview

jerboa-emacs is an Emacs-inspired editor built on top of:

The TUI backend runs in a terminal using Scintilla's text model. The Qt backend provides a full graphical interface.

Dependencies

Required (TUI backend)

Dependency Purpose Location
Chez Scheme ≥ 9.6 Scheme runtime system
jerboa Gerbil-compat stdlib vendor/jerboa
jerboa-shell (jsh) Shell interpreter vendor/jerboa-shell
jerboa-sqlite SQLite bindings used by jsh vendor/jerboa-sqlite
jerboa-lsp Optional Jerboa language server vendor/jerboa-lsp
jerboa-scintilla Scintilla editor FFI vendor/jerboa-scintilla
jerboa-pcre2 PCRE2 regex FFI vendor/jerboa-pcre2
PCRE2 development headers Native regex library system
libvterm development headers Terminal emulation shim for make binary system

On Debian/Ubuntu, install the native build prerequisites with:

sudo apt-get install build-essential pkg-config libpcre2-dev libvterm-dev

Additional (Qt backend)

Dependency Purpose Location
Qt 5 or Qt 6 GUI framework system
QScintilla Qt Scintilla widget system
jerboa-qt Qt FFI bindings vendor/jerboa-qt

Build

All commands run from the project root.

Jerboa build tools

make build and make binary build and use the vendored Jerboa multicall toolchain at vendor/jerboa/dist/{jerboa,jerbuild}. The editor vendors and builds its native Scheme/FFI dependencies under vendor/.

For systems that have the standalone Jerboa release toolchain but no full Jerboa runtime checkout, use:

make ensure-jerboa-tools
make build-jerbuild
make jerbuild-check

ensure-jerboa-tools follows the same convention as jerboa-code and jerboa-shell: it prefers project-local tools, a sibling ../jerboa build, or PATH, and otherwise downloads jerboa-${JERBOA_VERSION} into .jerboa/bin. Downloaded toolchains are accepted only when their target-specific SHA-256 matches dependencies.lock; a checksum fetched beside the artifact is not a trust root. The .jerbuild* configs describe native target-host builds for macOS/Linux/ FreeBSD without requiring an installed full Jerboa runtime. Release targets use the exact vendored jerbuild and statically link its pinned libjerboa_native.a; failing crypto/TLS placeholder stubs are not part of release binaries.

Cross and target builds

Linux and FreeBSD target artifacts are built with jerbuild on the target OS. From macOS, the Linux amd64 target uses SSH by default:

make linux-amd64   # writes ./jemacs-linux-amd64

The default SSH host is linux.cons.io; override it with LINUX_BUILD_HOST=host and LINUX_BUILD_ROOT=/path/to/jerboa-emacs.

Linux arm64 and FreeBSD follow the jerboa-shell pattern and are built on a matching target host:

make linux-arm64   # on Linux arm64, or set LINUX_ARM64_BUILD_HOST
make freebsd-amd64 # writes ./jemacs-freebsd-amd64

Native target-host jerbuild configs are also available:

jerbuild build --config .jerbuild.linux-amd64
jerbuild build --config .jerbuild.linux-arm64
jerbuild build --config .jerbuild.freebsd-amd64

Vendor dependencies

make vendor-deps

This fetches the exact full commits recorded in dependencies.lock into vendor/ and rejects an existing checkout at any other revision. Archive, container, static OpenSSL 3.5.7 LTS, Chez, and Tree-sitter inputs are likewise digest- or commit-pinned. The default make build target verifies this graph first; make vendor-update never follows a mutable upstream head.

Build library modules

make build

This runs jerbuild to translate .ss Gerbil-syntax source files in src/ to Chez-compatible .sls library files in lib/. The build is incremental.

To force a full rebuild:

make rebuild

Build the jerboa-shell (jsh) library

The shell interpreter must be compiled separately:

cd vendor/jerboa-shell
make jsh-compile

Run (TUI mode)

make run

This builds and launches the terminal editor.

Run (Qt mode)

make run-qt

Requires the Qt backend build (see below).

Authenticated local control sockets

--repl PORT enables the full-power loopback debug REPL. It always requires a fresh 256-bit token, atomically published with the port in the mode-0600 ~/.jerboa-repl-port file. The always-on jerboa-client IPC endpoint uses an independent token in ~/.jemacs-server. Both endpoints enforce bounded input, deadlines, and one active connection. See docs/repl-server.md for the protocol and threat model.

Build Qt backend

make build-qt

The Qt backend consists of 45 modules in src/jerboa-emacs/qt/ (~48,801 lines). make build-qt simply runs the normal make build (which translates those .ss modules to .sls alongside the rest of the editor) and then prints a status banner — it does not compile a Qt binary by itself. To launch the Qt frontend interpreted, use make run-qt; to produce a static jemacs-qt binary, use make static-qt (below).

Static binaries (Podman / Linux host)

make static-qt   # fully static jemacs-qt, built via Podman (Containerfile.qt)
make static-tui  # static TUI binary, built on a prepared Linux host

static-qt routes to podman-static-qt, which builds with Podman and copies the resulting jemacs-qt out of the image. The *-podman targets (podman-deps, linux-static-qt-podman, linux-static-tui-podman, ...) use the same PODMAN, PODMAN_PLATFORM, PODMAN_BUILD_FLAGS, and PODMAN_RUN_FLAGS variables.

Testing

Run all standard tests

make test

The suite includes hostile authentication, overlong-frame, traversal, endpoint symlink, private-temp-file, and shell-metacharacter argv tests.

This runs: test-tier0, test-tier2, test-tier3, test-tier4, test-tier5, test-org, test-extra.

Run specific test suites

Command Description
make test-functional Functional dispatch chain tests (250 tests)
make test-term-hang Subprocess/blocking behavior diagnostic (13 tests)
make test-tier0 Core data structures
make test-tier2 Buffer and window primitives
make test-tier3 Editor core operations
make test-tier4 Shell integration
make test-tier5 Full editor commands
make test-org Org-mode subsystem

Environment for tests

The Makefile sets these automatically:

LD_LIBRARY_PATH = vendor/jerboa-pcre2:vendor/jerboa-scintilla:vendor/jerboa-qt:vendor/jerboa-shell
JERBOA_SCINTILLA_LIB = vendor/jerboa-scintilla
JERBOA_PCRE2_LIB = vendor/jerboa-pcre2

Release Evidence

Local release candidates use:

make audit
make sbom
make reproducibility-report
make editor-flow-evidence
make release-evidence

make release-evidence writes dist/release-evidence/ with test, audit, SBOM, reproducibility, target-host editor-flow status, build-environment, git-status, release-input, and binary hash evidence. See docs/release-evidence.md for the contents and remaining target-host review requirements.

Source Layout

src/
  jerboa-emacs/
    core.ss           — App state, frame, window data types
    buffer.ss         — Buffer management
    editor-core.ss    — Core editor commands
    editor.ss         — Command registration
    editor-cmds-a.ss  — Commands A-M
    editor-cmds-b.ss  — Commands N-Z, git operations
    editor-cmds-c.ss  — Additional commands
    shell.ss          — Shell integration (jsh-based)
    subprocess.ss     — Non-blocking subprocess execution
    terminal.ss       — Terminal emulation
    keymap.ss         — Key binding system
    helm.ss           — Helm completion framework
    persist.ss        — Session persistence
    editor-extra-*.ss — Extended features (org, AI, VCS, media, etc.)
    qt/               — Qt graphical backend (45 modules)
lib/
  jerboa-emacs/       — Generated .sls files (DO NOT EDIT)
tests/
  test-functional.ss  — Dispatch chain integration tests
  test-term-hang.ss   — Subprocess blocking diagnostic
  test-tier*.ss       — Tiered unit tests
  test-org-*.ss       — Org-mode tests

Architecture Notes

jerbuild code generation

.ss files in src/ use Gerbil-style syntax (def, defstruct, :module/path imports). The jerbuild tool (from jerboa) translates these to Chez Scheme .sls library files in lib/. Never edit .sls files directly — all changes go in .ss sources.

Qt backend and port ordering

Chez Scheme's open-process-ports returns values in this order:

(values write-stdin-port read-stdout-port read-stderr-port pid)

This differs from Gambit/Gerbil's open-process. All process I/O code uses this order.

Shell integration

The shell.ss module embeds the jsh POSIX shell interpreter. The subprocess.ss module provides run-process-interruptible for non-blocking subprocess execution with C-g interrupt support — this is the recommended path for long-running commands.

Note: gsh-capture / command-substitute in jsh uses open-output-file "/dev/fd/1" which acquires a Chez port registry lock. Running this in a secondary thread can deadlock with Chez's scheduler. Use run-process-interruptible for subprocess output capture in threaded contexts.

with-output-to-string

In Chez Scheme, with-output-to-string takes only a thunk:

(with-output-to-string (lambda () (display-exception e)))

The Gerbil form (with-output-to-string "" thunk) is not valid in Chez.

Key Variables (Makefile)

Variable Default Description
SCHEME vendor/jerboa/.chez/bin/scheme Chez Scheme executable
JERBOA vendor/jerboa jerboa checkout
JSH vendor/jerboa-shell/src jsh source path

Override on the command line: make SCHEME=/usr/local/bin/chez build

Documentation

Document Description
docs/jemacs-vs-emacs.md Feature comparison with GNU Emacs (48 categories, 2168+ commands)
docs/helm.md Helm narrowing framework — architecture, matching engine, sources
docs/shell.md Shell integration plan — jsh POSIX shell embedding
docs/repl-server.md TCP debug REPL server for live introspection
docs/50-features.md 50 features roadmap to close the gap with GNU Emacs