jglot More seriousLess serious

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

ProjectAreaDescriptionImplementation
nakterhusMarineData hub for a sailing boat: charts, instruments, cameras, dashboards and a logbook, served from a Raspberry Pi.Python, JavaScript, SQLite
jsailSimulationSailing simulator that computes the forces on a yacht and displays them in a 3D view.Rust, Godot 4, GLSL
rakemooner3D printingRecorder for Klipper 3D printers. It stores the complete telemetry of every print and plays it back.Rust, JavaScript
bidibok3D printingCommand-line tool and library for the Qidi Box filament feeder and dryer.Rust
jbuilderCADViewer and debugger for CAD models written in Python with build123d.Python, JavaScript
jcatTerminalImage viewer for terminals with the kitty graphics protocol. With the companion program modelrender it also displays 3D models.Python
jpimPersonal informationTodos, calendar and notes that are linked to existing files and directories.Rust, Svelte, SQLite
jphonePhoneAccess to the messages, contacts, camera and location of an Android phone from a desktop computer.Go, Svelte, Kotlin
jstatusMonitoringTerminal dashboards for machine and network status, with a tiling layout and a built-in layout editor.Go, C
jloggerLoggingCentral 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.
Browser Navigate workspace with a route from Lymington to Cowes, AIS targets, the course panel and the bow camera. The data comes from the simulator, as the indicator in the header shows.

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 check lists 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.
Desktop 3D view with the autopilot steering for a mark to windward: 5.81 kn, 18° of heel. The arrows show the load on each strip of sail. The panel at the lower left marks strips that are luffing or stalled.

Details

Interfaces
3D application built on Godot; headless jsail CLI
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

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.
Browser Model workspace: a vase at layer 529 of 700, coloured by height and placed on the bed mesh that was measured before the print.

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

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 sync writes 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).
Command line 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

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.
Browser A wall bracket for a desk lamp. The fillet between the arm and the plate is selected, and the source panel shows line 52, 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 hjkl keys; n and p move 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.
  • --place draws 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.
Terminal A Julia set image of 4,800 pixels at 100 %, panned. The status line is the only interface element.

Details

Commands
jcat and modelrender
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

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, +project and due:. Example: varnish the tiller #boat @boatyard due:fri +marigold.
  • A command bar, opened with :, in the terminal interface and the web application. It accepts any jpim command.
  • 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.
Browser Today view in the web application: tags, places, overdue deadlines, and the files that a todo refers to.

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 .gitignore rules 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

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.
Terminal Messages in the terminal interface: six unread conversations and one open conversation with a photo rendered by jcat.

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

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: v and s split a panel, HJKL move 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.
Terminal Overview dashboard: clock, local machine, six hosts of which one has been unreachable for 3 h 22 min, recent log entries from another machine, and the appointments of the day.

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 verify checks 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.
Browser Web viewer with entries of severity warning and above, sorted by severity. The entries include a mains power failure and a soil sensor with implausible readings.

Details

Interfaces
Daemon; jlog CLI; terminal viewer; web viewer; zsh client that requires only jq
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

Common conventions

The projects are separate programs, but they are built to the same rules.

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.