jglot project overview
Ten self-hosted programs for boat instrumentation, 3D printing, CAD, terminal graphics, personal information management, phone access, monitoring and logging.
The jglot projects are developed for one private network, which includes a sailing boat, a workshop with a 3D printer, a phone, and a number of desktop and server machines. Each project is an independent program. They are documented together because they follow the same conventions and because several of them use each other.
The software is written by a single maintainer with the assistance of a large language model. Platform and implementation details are listed in each project section.
All screenshots on this page show the programs themselves, running on invented data.
Projects
| Project | Area | Description | Implementation |
|---|---|---|---|
| nakterhus | Marine | Data hub for a sailing boat: charts, instruments, cameras, dashboards and a logbook, served from a Raspberry Pi. | Python, JavaScript, SQLite |
| jsail | Simulation | Sailing simulator that computes the forces on a yacht and displays them in a 3D view. | Rust, Godot 4, GLSL |
| rakemooner | 3D printing | Recorder for Klipper 3D printers. It stores the complete telemetry of every print and plays it back. | Rust, JavaScript |
| bidibok | 3D printing | Command-line tool and library for the Qidi Box filament feeder and dryer. | Rust |
| jbuilder | CAD | Viewer and debugger for CAD models written in Python with build123d. | Python, JavaScript |
| jcat | Terminal | Image viewer for terminals with the kitty graphics protocol. With the companion program modelrender it also displays 3D models. | Python |
| jpim | Personal information | Todos, calendar and notes that are linked to existing files and directories. | Rust, Svelte, SQLite |
| jphone | Phone | Access to the messages, contacts, camera and location of an Android phone from a desktop computer. | Go, Svelte, Kotlin |
| jstatus | Monitoring | Terminal dashboards for machine and network status, with a tiling layout and a built-in layout editor. | Go, C |
| jlogger | Logging | Central log server for a private network, with a hash chain that makes modification of stored entries detectable. | Go, SQLite |
Marine
nakterhus
Data hub for a sailing boat: charts, instruments, cameras, dashboards and a logbook, served from a Raspberry Pi.
nakterhus collects the data of a sailing boat and presents it as charts, instrument displays, dashboards and a logbook. It runs on a Raspberry Pi 4 on board and subscribes to the boat’s SignalK server. Every received delta is written to SQLite, so a passage can be examined after the event. The name is the Swedish word for binnacle.
The command tree is defined once and is available both in a shell and in a console in the web interface. Dashboards are written as HTML fragments and rendered by two renderers, the browser and a native renderer for the e-paper panel; a test compares the two results.
The system is designed for a metered 4G connection. A camera stream is an ffmpeg process that runs only while a client is viewing it, clients outside the boat’s network receive a lower frame rate and resolution, and a phone page that is not visible stops polling.
Features
- Charts based on OpenStreetMap and OpenSeaMap, with route overlay and AIS targets. For each target the closest point of approach is calculated.
- Seven workspaces: Navigate, Helm, Plan, History, Voyage, Dashboards and Sail. They are selected with the digit keys and remain mounted when another workspace is shown.
- Playback of recorded data. The graphs and the track on the chart are positioned by a common time cursor.
- Sail trim guidance: the current point of sail, a reefing recommendation, and an ordered list of trim steps with the reason for each.
- The data source, boat or simulator, is detected and cannot be set. Simulated data is marked in the interface.
- A phone page that can be installed as an application and keeps the display on.
- An e-paper repeater of 800 × 480 pixels at one bit per pixel, updated once per second.
Details
- Platform
- Raspberry Pi 4, Debian 13
- Interfaces
- Web interface with seven workspaces; phone page; CLI with about 35 command groups; 7.5-inch e-paper panel
- Implementation
- Python with three runtime dependencies; ES modules without a framework; Leaflet; three.js; SQLite
- Integrations
- SignalK, AIS, Victron power equipment, USB cameras, 4G router
- Status
- In use on board. 1,058 commits since May 2026; approximately 1,860 tests
- Source code
- Not yet public
Screenshots
Simulation
jsail
Sailing simulator that computes the forces on a yacht and displays them in a 3D view.
jsail simulates a sailing yacht and shows the quantities it has computed. The model covers the aerodynamics of the sails, the hull, keel and rudder, and the wind, current and waves acting on them. In motion the boat is integrated in six degrees of freedom. The rudder angle is solved together with yaw, so weather helm and broaching are outcomes of the model and not parameters.
The simulation does not depend on the display. A headless build provides the same computations as a command-line program for polars, timed runs and checks of boat files.
Features
- Force display: the load on each strip of sail, the pressure distribution along the luff, streamlines coloured by speed relative to the wind, and the righting and heeling arms in metres.
- Eight trim controls, each with an Auto option. Controls left on Auto are optimised around the values that were set manually.
- Instructor mode for a poorly trimmed boat. It gives one correction at a time, with the reason, the expected gain in knots and a marker on the control concerned.
- Trim changes are applied at the speed of a winch, and the speed lost in a tack is a result of the model.
- Boat files record the origin of every value as declared, calculated or estimated.
jsail boat checklists the estimated values. - Conditions outside the limits of the boat are reported as such, for example that no sail configuration can be carried in 14 m/s of wind.
Details
- Interfaces
- 3D application built on Godot; headless
jsailCLI - Implementation
- Rust workspace of six crates; Godot 4 through gdext; GLSL shaders for water, sails and flow
- Validation
- Compared with WinVPP polars and the Delft Systematic Yacht Hull Series: RMS deviation 0.42 kn over 224 cells
- Headless build
- 2.1 MB binary; computes a polar in less than 0.1 s on a Raspberry Pi
- Status
- First iteration complete; the boat can be sailed
- Source code
- Not public
Screenshots
jsail polar. At 19 kn of wind the automatic trim flattens the sails and then reefs.jsail sail: one tack at one-second intervals. The speed drops from 5.85 kn to about 2 kn and recovers.3D printing
rakemooner
Recorder for Klipper 3D printers. It stores the complete telemetry of every print and plays it back.
rakemooner records what a Klipper printer does during a print and keeps the record for later review. Moonraker reports the current state of the printer; rakemooner adds the history. A daemon samples temperatures and their targets, heater power, fans, speed and the humidity of the filament enclosure once per second, and stores the console output, the bed mesh and the webcam video with them.
The web interface replays a print from a single time cursor. Moving the cursor in a chart also positions the readouts, the current G-code line, the 3D toolpath and the video.
Prints are assigned to projects automatically. A model version is identified by a hash of its meshes. The settings that changed between two prints are read from the configuration block that the slicer writes at the end of the G-code.
Features
- 3D toolpath drawn as boxes with the actual width and height of each extrusion, in a single draw call. A ten-hour print has about 1.5 million of them.
- Toolpath colouring by feature type, speed, height, filament slot or any other recorded field.
- Comparison of two prints, with a list of the settings that differ.
- Slicer workspace: slices the slicer project of a print again with changed settings, using the OrcaSlicer command line, and compares print time and material.
- Workspaces remain mounted when another one is shown. The webcam stream continues and text that has not been saved is kept.
- Dew point calculated from the temperature and humidity in the filament enclosure.
Details
- Interfaces
- Recorder daemon; web interface with a phone layout;
rm-cli; desktop shell - Implementation
- Nine Rust crates using tokio, axum and Tauri; JavaScript and three.js without a build step
- Recorded data
- Sensors at 1 Hz, G-code, console output, bed mesh, webcam video
- Dependencies
- Moonraker for printer access, ffmpeg for video, the OrcaSlicer command line for re-slicing
- Status
- In daily use. 243 commits since May 2026
- Source code
- Not yet public
Screenshots
rm-cli: status, project list, a comparison of two prints, and a slice with two settings changed.3D printing
bidibok
Command-line tool and library for the Qidi Box filament feeder and dryer.
bidibok controls the Qidi Box, the unit that feeds a Qidi Q2 printer from four spools and dries the filament. It provides the functions of the printer’s touchscreen as commands, so they can be used in scripts, and as a library crate for other programs.
A simulated printer is part of the project. It executes the G-code it receives against a model of the box, with the timing of the firmware: a load operation blocks for several seconds, a drying cycle heats the box, and the humidity falls. The tests and the screenshots on this page use the simulator.
Features
- Reports the state of the box and of each slot, including sensors, endstops and heater.
- Loads and unloads filament; starts and adjusts drying cycles.
- Reads the RFID tag of a spool and assigns filament type, colour and vendor from it.
- Shows filament colours as 24-bit swatches. They are omitted when the output is not a terminal.
- User-defined filaments are kept in a local file and overlaid on the printer’s list by index. After a firmware update has replaced the printer’s list,
preset syncwrites the user’s entries back and leaves the stock entries unchanged. - Exit codes separate failures that may succeed on a later attempt (1) from failures that will not (2).
bidibok slot list: four slots with four different filaments. Slot 1A is feeding the printer, and the box is in a drying cycle at 55 °C with eight hours remaining. No slot can substitute for another.Details
- Interfaces
- CLI; Rust library crate
- Implementation
- Rust: protocol core without I/O, command-line front end using clap, simulated printer
- Protocol
- Moonraker over HTTP. No SSH access, and no software on the printer
- Firmware
- Two generations supported, detected at run time
- Tests
- 137 golden-file tests. None requires a printer
- Source code
- Not yet public
Screenshots
bidibok status and sensor readings: firmware, endstops, heater at 5 % power, 6 % relative humidity.CAD
jbuilder
Viewer and debugger for CAD models written in Python with build123d.
jbuilder is a development tool for solid models that are defined as Python scripts using build123d. It watches the script and rebuilds the model whenever the file is saved, from any editor.
While the script runs, a trace hook records which source line creates each face, edge and vertex. This record connects the geometry in the viewer to the source code. A face that later operations do not change keeps its original line through subsequent cuts and fillets.
Features
- Source navigation: selecting a face, edge or vertex in the viewer shows the line of the script that created it.
- Selector suggestions for the selected shape. Candidate expressions are generated and evaluated, and only those that resolve to exactly that shape are returned: at most three, the simplest first. The suggestions come from a deterministic algorithm.
- Selector input with highlighting of the matching shapes and a match count while typing.
- Line preview: selecting a line number displays only the geometry created by that line.
- Checkpoints: a call to
show()in the script defines a named, coloured intermediate state. It is rendered only when it is selected. - Constraint sketcher that can be opened on any planar face.
- Scratch buffer that shares the namespace of the model.
- Neovim plugin: build errors are reported as diagnostics, and the viewer follows the cursor.
part = fillet(root, 5).Details
- Interfaces
- Web viewer; desktop window;
jbuilder-cli; Neovim plugin - Implementation
- Python with FastAPI and build123d; Three.js and CodeMirror without a build step
- Export formats
- STL, STEP, BREP, glTF, 3MF
- Source files
- Read only. jbuilder does not modify model code
- Source code
- Not yet public
Screenshots
Terminal
jcat
Image viewer for terminals with the kitty graphics protocol. With the companion program modelrender it also displays 3D models.
jcat displays images in a terminal that implements the kitty graphics protocol. It is an interactive viewer with zoom and pan, and it can also be called by other programs to place a single image.
modelrender is a second program in the same project. It renders a 3D model as a sheet of views with the hidden lines removed. A depth buffer is rasterised only to determine which edges are visible, and the result is written as vector paths.
When modelrender is installed, jcat opens model files in the same way as images, for example jcat bracket.stl. Progress is indicated while FreeCAD tessellates the model.
Features
- Zoom with the mouse wheel; pan by dragging or with the
hjklkeys;nandpmove between the files given on the command line. - The image is transmitted once. Each zoom or pan step is a placement command of a few dozen bytes, and the terminal performs the scaling.
- Vector formats are rasterised at twice the screen resolution.
- SSH sessions are detected, and the image data is then streamed instead of being passed as a file.
- tmux is supported with a separate method: Unicode placeholder cells, an image pyramid, and two alternating image IDs so that no blank frame is shown.
--placedraws one image into a given block of cells and exits. Other programs use this to display images.- modelrender produces up to nine views of a model on one sheet, with hidden lines removed. All views of a sheet have the same scale. The output consists of vector paths.
Details
- Commands
jcatandmodelrender- Implementation
- Python. jcat uses Pillow and ImageMagick; modelrender uses trimesh, numpy and FreeCAD without its interface
- Image formats
- Bitmap formats, SVG, PDF, HEIC
- Model formats
- STL, 3MF, OBJ, glTF; STEP, IGES, BREP and FreeCAD documents
- Status
- jcat is a prototype. Its implementation notes are written for a later rewrite
- Source code
- Not yet public
Screenshots
modelrender: listing the bodies of a document and rendering two of them, with a progress bar during tessellation.Personal information
jpim
Todos, calendar and notes that are linked to existing files and directories.
jpim manages todos, appointments and notes. It is designed as a layer over the directories, notes and source files that already exist, and not as a separate place for them. Items can be created through any of the interfaces or declared in a file.
All functions are provided by a daemon over HTTP, and every endpoint is available as a CLI command. The other interfaces use the same commands.
Features
- Directives in files: a comment such as
@jpim { kind = "todo" }in any text file defines an item. The file remains the authoritative source, and editing the line updates the item. - Files are modified only on request. jpim can then write an eight-character identifier into the directive, so that the item is still recognised after the line has been moved.
- One quick-add syntax in all interfaces, with
#tag,@place,+projectanddue:. Example:varnish the tiller #boat @boatyard due:fri +marigold. - A command bar, opened with
:, in the terminal interface and the web application. It accepts anyjpimcommand. - A due date without a time refers to the end of that day.
- The calendar in the terminal interface is the output of the CLI and has no separate implementation. Its markers can be told apart without colour: a dot for an appointment, a diamond for a deadline, a triangle for an overdue item.
- Places are defined as named circles on a map. A todo can be assigned to a place.
Details
- Interfaces
- Daemon; CLI; terminal interface; web application; desktop shell; Neovim plugin; tmux popup
- Implementation
- Rust with axum, SQLite, ratatui and Tauri. The web application is written in Svelte and embedded in the daemon
- API
- 35 endpoints. Each has a CLI command; the build fails if one is missing
- Scanner
- Follows
.gitignorerules and caches its results. A repeated scan of a 37 GB project takes about two seconds - Status
- All planned interfaces are implemented
- Source code
- Not yet public
Screenshots
@jpim directive found in the source files of a project, with file, line and the TOML text.#varnish.Phone
jphone
Access to the messages, contacts, camera and location of an Android phone from a desktop computer.
jphone makes the functions of an Android phone available on a desktop computer: text messages, contacts, camera, location and device status. It consists of a command-line program, a terminal interface and a web application on the computer, and an application on the phone.
The phone does not connect to a dedicated server. The Android application logs in over SSH to a restricted login shell and keeps one long-running wait command open, which serves as the push channel.
The terminal interface and the web application do not read data files. Each view is built from CLI output and each action runs a CLI command, so every function exists once and can be used in scripts.
Features
- Five sections: Messages, Contacts, Camera, Location and Status.
- The SMS composer counts the parts of a message while it is typed. It identifies the character that changes the encoding and reduces a part from 160 to 70 characters.
- Photos are displayed as images in the terminal.
- Photos can be taken from the computer. Comments and tags are stored in the JPEG file itself.
- Location: a current position fix on request, recording of tracks, and a ring at full volume that also sounds when the phone is silenced. The ring is stopped with a button on the phone.
- Messages are marked as read only when they are displayed in a visible view.
Details
- Interfaces
- CLI; terminal interface with five tabs; web application; Android application on the phone
- Implementation
- Go with Bubble Tea on the computer; Svelte in the browser; Kotlin on the phone
- Transport
- SSH over WireGuard, one command per request. No listening port is added on either side
- Wake-up
- One UDP packet. The phone responds from deep doze within two to four seconds
- Uses
- jcat for photos, jkarta for maps, jpim for the notes and todos related to a contact
- Source code
- Not yet public
Screenshots
p key takes a new photo.Monitoring
jstatus
Terminal dashboards for machine and network status, with a tiling layout and a built-in layout editor.
jstatus shows status information as dashboards in a terminal. A dashboard is a tab, and a tab consists of widgets in framed panels that are arranged in nested boxes. Dashboards are defined per computer, because the relevant information differs between a laptop and a server.
A daemon monitors the configured hosts continuously. The duration of an outage is therefore correct even if no dashboard was open while it occurred. A dashboard reaches the daemon through an SSH connection, so access is controlled by SSH login.
Features
- Widgets for the local machine: processor load and its history, memory, sensors, disks and disk I/O, network, and processes.
- Widgets for other sources: reachability and latency of hosts, recent jlogger entries, the jpim calendar, a clock, and
command, which frames the output of any program. - Layout editor with the key bindings of a tiling window manager:
vandssplit a panel,HJKLmove it, two marked panels can be swapped, and changes can be undone. A wireframe shows the layout at its size in terminal cells. - Widgets reduce their content in a documented order when space is limited. A chart becomes a sparkline and is then omitted, and table columns are removed in a fixed sequence.
- The sensors widget does not query an idle graphics card, because the query would prevent the card from suspending.
- A configuration file with errors is shown as a tab with a warning. The other dashboards are not affected.
Details
- Interfaces
- Terminal interface; monitoring daemon; desktop window without decorations
- Implementation
- Go with Bubble Tea and Lip Gloss. The desktop window is 280 lines of C using GTK and VTE
- Configuration
- KDL, one file per dashboard, or the built-in editor
- Widgets
- Sixteen types
- Daemon access
- HTTP through
ssh -W. The daemon has no authentication of its own and no open port - Source code
- Not yet public
Screenshots
Logging
jlogger
Central log server for a private network, with a hash chain that makes modification of stored entries detectable.
jlogger receives log entries from the machines and scripts of a private network and stores them in one place. Typical sources are scheduled jobs, backup scripts, sensors and printers.
Each entry is stored together with the hash of the entry before it. The chain starts at an entry whose predecessor is the string genesis. A change to any stored row invalidates the hash of every later entry, so the modification can be detected and located.
Features
- Verification:
jlog verifychecks the chain and reports the id of the first entry that does not match. - Additional protection against modification: a second, append-only copy of the log, and a service account without capabilities.
- Any host on the network can submit entries. A client can sign its entries; the server verifies the signature before it accepts a signed entry.
- The command that submits an entry always exits with status 0. A log server that cannot be reached does not cause the calling job to fail.
- Log content is treated as untrusted. It is stored unchanged, and the viewers escape control characters and bidirectional override characters when they display it.
- The web viewer requests new entries every three seconds. When the list is sorted by a field other than time, new rows are not inserted; the viewer shows how many are waiting.
- Filters for host and minimum severity. The web viewer has seven themes.
Details
- Interfaces
- Daemon;
jlogCLI; terminal viewer; web viewer; zsh client that requires onlyjq - Implementation
- About 2,600 lines of Go; SQLite in a pure Go implementation; HTML rendered on the server
- Integrity
- SHA-256 chain over all entries; optional Ed25519 signatures from clients
- Platforms
- amd64, arm64 and armv7. Packages for Arch and Debian
- Source code
- Not yet public
Screenshots
jlog verify on an intact chain, and again after one row was changed directly in the database. The changed row is reported as the first invalid entry.nas: a nightly backup from its start to the off-site synchronisation, in the Gruvbox theme.Common conventions
The projects are separate programs, but they are built to the same rules.
- Command-line interface. Each project provides a complete command-line interface. In several projects the terminal and web interfaces are built on the output of that interface and do not access the data directly.
- Services. Background services are small, single-purpose processes. They listen on the loopback interface or on a private network only.
- Data. All data is stored on machines operated by the user. No project depends on an external hosted service.
- Integration. A project that needs a function of another project runs that project’s command-line interface and reads its output. Each project remains usable without the others.
Availability
The source repositories are not public at present. If a repository is published, the corresponding project section on this page will link to it.
Questions about the projects can be sent to info@jglot.com.