A Java-based graphical browser for Gemini and other 'small net' protocols
Version 1.0.0, Kevin Boone, April 2026
Note
Caztor 1.0 is a development of JGemini, but it's radically different in many
ways. I added a lot of code in a relatively short time, as well as refactoring
a lot of the original code. Caztor is, I hope, a better application by far than
JGemini, but adding new features this quickly comes with risks. Although
Caztor is stable enough for my own purposes, it's plausible that I've broken
features that worked before. If you find bugs, do please report them. Thank
you.
Note
Caztor won't use a JGemini configuration. For Linux users, there's a script
in the samples/ directory that will try to convert JGemini settings
to Caztor settings.
Caztor is a graphical client for the Gemini, Spartan, Gopher, and "Nightfall
Express" (nex) protocols. It looks and behaves rather like the first
graphical Web browsers from the 90s. So far as I know, it supports all the
features it is required to support by the various specifications, and little
else. It's useable, though: I use it every day.
There's no good reason. I wrote JGemini, as it then was, a long time ago, before there were any reasonable graphical clients for the Gemini protocol for Linux. Times have changed, and there are a number of clients for Linux that are superior to Caztor: Lagrange and Alhena, for example. I maintain Caztor for my own experiments, and because it works exactly as I want it -- I doubt it would be much use to anybody else.
Still, there are a few reasons why you might, maybe consider Caztor over the other browsers available.
- Caztor has full, native Markdown support
- Privacy -- Caztor saves no state except what the user expressly allows, and even then not much
- Caztor is cross-platform; the same code runs on every supported platform
- Few dependencies: Caztor requires a Java JVM, any version from 11 onwards
To run Caztor you'll need a computer with some kind of graphical desktop, and a Java JVM. Caztor should work with any Java version 11.0 or later. I've tested it with OpenJDK versions 11-27. If you want to build Caztor from source, you'll probably need Maven.
Caztor is intended for Linux. It works on other platforms with a relatively modern JVM, including Windows 11, but I don't care about, or do much testing on, anything except Linux.
If you're looking at Gemini/Spartan capsules that use Unicode emojis -- and
many do -- you'll probably need to ensure that your computer has fonts that
contain the relevant glyphs; see docs/emoji_support.md for more information.
If you want to stream Gemini radio and similar content, you'll need a media
player that Caztor can send a data stream to; VLC and ffmpeg both seem to
work.
- No specific installation procedure (if you have a Java JVM) -- Caztor is supplied as a single Java JAR file
- Supports Gemini, Spartan, Gopher, and
nexprotocols - Handles Gemtext, CommonMark Markdown, and plain (usually UTF-8) text
- Renders local files as well as remote content
- Authentication using per-server client certificates
- Built-in client certificate manager, which can create new certificates and incorporate existing ones
- Text styling can be configured to suit the display and user preference
- Uses anti-aliased font rendering for a smoother text appearance
- Fetches documents asynchronously to improve user interface responsiveness
- Download manager
- Text selection with cut-and-paste
- Search in document
- Supports multiple windows
- Search directly from the URL bar
- Saves little state by default, for privacy
- Reasonably comprehensive documentation with built-in viewer
- Rudimentary bookmark support, with built-in editor
- Rudimentary media streaming support, using an external player
- Parses and displays Atom feeds
Caztor does not need to be installed, beyond copying its JAR file to some
convenient place. However, a more formal installation might be more convenient.
For more information, please see the separate document
README_installation.md. In essence, just run the Caztor JAR file using the
Java JVM.
Nearly all Caztor's features can be configured using the Settings dialog in the main user interface. It should no longer be necessary to edit the configuration file very often, if at all. However, it's still possible, it's still documented, and Caztor has a built-in file editor for doing it, should the need arise.
Caztor supports JPEG, PNG, and GIF images internally, including animated versions.
For Gemini and Spartan, supported images will be displayed in-line in the document by default. Links to other types -- and to other types of document entirely -- will just be displayed as a link.
For compatibility with other Gemini browsers, Caztor can be configured not
to in-line images from a Gemtext document into the text if preferred. The
configuration property is gemtext.inline.images=1|0. If images are not
in-lined, they will be rendered as links, just as for unsupported image types.
Images referenced from gophermaps (directories) will never be in-lined. It's common to find gophermaps with huge numbers of huge images, because Gopher authors don't expect images to be in-lined.
Images in-lined into a document are all displayed with the same (configurable) size. This is because none of the document formats which Caztor supports allow an image size to be specified, and it looks odd if they're all different sizes.
If you choose to open a document explicitly, it will be displayed at its full size.
Images are fetched asynchronously. It's not always easy to tell when this is happening, except that images areas on the screen will be blank. If you select to open an image in a new window, you'll see a blank screen until the image is fully downloaded. Please be patient -- Gemini does not provide a way to know in advance how large the image is, so Caztor can't report progress.
Although the widths of in-line images will all be the same, heights might be different, to keep the correct aspect ratio. Because Caztor does not know the total size of an image until it's been retrieved, the page might redraw after downloading an in-line image.
Please note that the File|Save menu only saves text. You'll get an error message if you open an image in a new window, and then try to save it. If you want to save an image as a file, right-click its link and select 'Download'.
The ability to open an image in its own window is only available for images
whose paths end in a conventional extension, like .jpg. This is because
Caztor can't tell, just from a link URI, what kind of data the link provides.
An image file that can't be recognized from its filename will be downloaded and
handed off to the platform to handle.
Caztor remembers URLs you visit, either by entering them in the URL bar, or by following links. By default the history is not saved anywhere, because it's potentially a privacy risk. You can change this behaviour using the Settings dialog box.
By default, you can enter a search term in the URL bar, rather than a URL, as with most modern web browsers. You can disable this feature, or change the search provider, in the configuration file.
There's no perfectly reliable way for Caztor to know whether you've entered a search term or a URL. Since URLs usually contain periods ('.'), and don't usually contain spaces, this is used as a guide. However, just as web browsers do, Caztor will sometimes guess wrongly.
The usual arrow keys and page up/down should work. You can highlight text using shift+arrow combinations. To go to the top/bottom of the page, using ctrl+Home/End. Zoom in/out with ctrlr+[ and ctrl+].
When a server prompts for input, Caztor raises a text-entry dialog box. Since it's legitimate -- and commonplace -- for input to contain newline characters, the 'Enter' key does not submit the input, but enters a new line. To submit, hit ctrl+S.
Since a Gemini URL is limited to a total of 1024 bytes, and that has to include
the gemini://host/port/path part, the text input dialog box shows the number
of bytes remaining for user input. As you type, this number will decrease by an
amount which might not clearly be linked to the amount of input. This is a
consequence of the way non-alphanumeric characters have to be encoded, and the
fact that UTF-8 -- which Gemini expects -- is a multi-byte encoding.
Caztor uses the same text input box for Gemini and Gopher. Some Gopher servers may behave properly with non-ASCII input, but I suspect that many will not.
Caztor takes any Gopher URI that ends in '/' to be a reference to a gophermap (directory), and it parses the returned document accordingly. Except when following a link from a gophermap, Caztor has no reliable way to know what kind of data it is retrieving, except to guess it from the filename. Consequently, filenames are more important with Gopher than with Gemini. Broadly, Caztor will use file extensions to determine what to do with a file it gets from a Gopher server, more than is the case with Gemini.
Things are slightly more predictable when reading a gophermap, because this does give some indication of the file type. So Caztor will try to use icons to show the type of file the link references -- image, movie, text, etc.
Caztor can interpret Gopher URIs with or without a type character. That is, we might have:
gopher://foo.bar/file.txt
or
gopher://foo.bar/0/file.txt
Here the '0', which signifies a text file, is a guide to the browser, not the server. The server never sees the '/0' part of the URI, so it always sends the same thing. This odd convention came about because we needed a way to incorporate the type information from a gophermap into a URI.
Caztor always displays text files from Gopher as pre-formatted lines. Gopher dates from a time when everybody used 80-column screens, and documents are generally formatted on that basis.
Caztor supports Gopher queries, typically used with search engines like Veronica.
The Gopher specification calls for a text file to end with a period (.) on a line on its own. Not all authors or servers follow this rule. If this line does exist, Caztor displays it. It would be a hassle for it to have to use different logic to display text files from Gopher differently to all other text files.
Nightfall express is a very rudimentary protocol. Like Gopher, the browser has to rely on the filename, for deciding how to handle a file. However, there is no equivalent of a gophermap, so Caztor can't decorate links to indicate the type of file they reference, except by filename.
In practice, I've not see nex used for anything except plain text.
Like Gopher, text documents used with nex are generally pre-formatted for an 80-column screen, and Caztor displays them as such.
Caztor supports Gemini user input and redirections, as well as ordinary document retrieval. At present it doesn't support the Titan upload protocol. Gemini responses include a MIME type so, in principle, Caztor should be able to work out unambiguously how to handle the document it receives. However, when running Caztor with a local file, it still has to use the filename to guess the contents, so filenames are still important.
Caztor tries to annotate links to indicate the type of document they link to. However, it's common for Gemini authors to use emojis or unicode symbols to highlight particular functions or contents. So Caztor doesn't annotate links that appear to start with such characters. However, this is at best a guess.
Spartan is a simplified form of Gemini, without the TLS encryption. Caztor won't do user input with with Spartan, because the specification doesn't provide any way to do input or upload.
Caztor relies heavily on Java features that haven't changed since about 2005. Frankly, I'm surprised some of them still exist in the JDK. The user interface is based on that old warhorse, Java Swing. Internally, all document files are converted to HTML, and displayed using Swing's built-in HTML viewer. This viewer has not been updated for decades, but it's more than adequate to show Gemtext and Markdown content. In any event, it's possible that these features will be removed from Java at some point, or relegated to optional downloads. I'll find a way to deal with that, if the situation arises.
Please see the separate document ISSUES.txt.
To build Caztor from source, you'll need Maven, configured for the usual repositories (although Caztor has few dependencies). Then, in the source directory:
mvn package
This will generate the compiled JARs in target/.
Caztor is maintained by Kevin Boone, and distributed under the terms of the GNU Public Licence, v3.0.
The binary distribution includes a number of open-source libraries and
media items. For full details, please see docs/author_and_legal.md.
There is, of course, no warranty of any kind.
JGemini version 0.1 -- March 2021 -- first release
JGemini version 0.1a -- October 2021
- Added code to apply SNI header to the TLS communication (contributed by omar-polo)
JGemini version 0.1c -- June 2024
- Added a system-level configuration file
- Changed the default homepage
- Improved the documentation slightly
JGemini version 0.1d -- March 2026
- Updated documentation
- Added support for client certificate selection
- Fixed a bug with redirection
- Fix a bug with URL encoding in uploads
JGemini version 0.1e -- March 2026
- Improved Markdown support
- Added Go|Root
- Added styling for block quotes
- Improved the text entry dialog box, and added a character count
- Updated documentation a little
JGemini version 1.0f -- March 2026
- Added inline image support in Gemtext
- Added configuration for image size
- Added internal image handling for certain types of file
- Added dark configuration sample
- Added an indication of amount transferred in Gemini connection
JGemini version 2.0.0 -- March 2026
- Added preliminary Spartan, Gopher, and nex support
- Made Go|Root work better with URIs with usernames
- Added zoom in/out
- Completely changed the way styling works
- Took out handling of _ and * in Gemtext, because too many capsules used these in non-emphasizing ways.
- Implemented search from URL bar (which can be disabled)
- Let the desktop set the main window position, so Caztor windows don't appear on top of one another.
- Added documentation viewer
JGemini version 2.0.1 -- April 2026
- Added rudimentary settings editor
- Added "Set as home page" facility
- Changed location of properties file, in a new directory, which will also store URL history by default
JGemini version 2.0.2 -- April 2026
- Added rudimentary bookmark support
- Updated documentation, particularly related to emoji support
- Fixed bug in list formatting in Gemtext
- Put limit on status line in Gemini response, to protect against broken server
- Fixed (maybe) broken handling of selectors beginning "/" in Gopher
- Added converter for Atom feeds
- Updated documentation concerning emoji fonts
- Added open-source licences to the built-in documentation
JGemini version 2.0.3 -- April 2026
- Changed the button accelerators from ctrl-something to the platform default (typically alt-something).
- Moved all the user-visible text strings to resource bundles. What a horrible job -- I should have done it properly from the start
- Added rudimentary client identity manager
- Dialog-specific documentation
JGemini version 2.0.4 -- April 2026
- Added a way to show server certificate information
- Added a 'settings' dialog box
- Removed a bunch of superfluous menu commands, and rearranged some others
- Window size is now saved when closing a window
- Fixed a number of stupid bugs
- Added a "useful links" page
JGemini version 2.0.5 -- April 2026
- Tidied up the connection logic
- Intercepted requests for unhandled content types, and pop up a 'file save' dialog box
JGemini version 3.0.0 -- April 2026
- Download code completely rewritten
- Download manager implemented
- Rudimentary media streaming support: Caztor can launch a media player like VLC, and stream data into it retrieved using any of the protocols it supports
- URL bar now filters the URL history as the user types. This was surprisingly nasty to implement, and might be buggy
- Started to move comments to proper javadocs, and added a javadoc goal to the
Maven
pom.xml. Thejavadocs.shscript runs the Maven goal, and moves the generated documentation tojavadocs/ - Toolbar icon size is now configurable: setting
ui.icon.size - Toolbar icons can be colour/mono, using the setting
ui.icons.mono. Colour is the default - Caztor now does a proper "System.exit()" when it detects that no top-level windows are open. This should prevent the program hanging on exit because Swing leaves dangling threads that can't easily be closed. When exiting, Caztor cleans up incomplete file transfers
Caztor version 1.0.0 -- April 2026
- Feed aggregation support
- Complete renaming to suit the new "Caztor" name
- New logo and artwork
Caztor version 1.0.1 -- April 2026
- URL bar filtering now sorts matches in alpha order, which tends to put shorter URLs at the top. This needs careful monitoring, because the sorting operation is performed very frequently, and is computationally expensive
- You can now right-click an image to get the context menu, as well as the image's link text. This is important in Markdown documents, as there generally isn't any link text
- Added forward as well as back navigation
- Toolbar buttons and menus now enable/disable according to page contents
- Added a connection timeout that defaults to ten seconds
- Preliminary Demarkus browsing support
- Updated documentation