An IDE, but for files.
An editor gives a programmer one window in which to search a project, open several things at once, run tools over them and see the results — without ever reaching for a terminal or a second application. Mole sets out to be that window for files: browsing, searching, comparing, syncing, renaming in bulk, finding duplicates, previewing anything, and running long jobs in the background, all under one keyboard.
It is native and desktop-first, built on C++20 and Qt 6 / QML, and designed from the start so that drives and tabs are both plugin extension points: a tab is one workflow over files, and anything that can list and read entries can be a drive.
Status: early. The architecture is in place and covered by tests; features are being added on top of it.
- Virtual drives. Local disk, an in-memory scratch space and read-only
archives (zip, tar, 7z, ...) are all mounts of the same
IFileSysteminterface. Activating an archive mounts it and browses inside. - Tabs as workflows. Browser (single pane, dual pane, a grid of icons or a gallery of thumbnails), search, previews, reports and the rest — each a separate feature, opened from the same menu.
- Filter by typing. Start typing in a listing and it narrows to what you
typed — no shortcut, no storage access. A search that walks the tree is a
separate tab on
Ctrl+F. - One search, asked a dozen ways. A name as text, a shape or an expression;
a path; a size; dates typed the way people say them (
last 7 days,>30d); what a file is rather than what it is called; folders to skip; and the text inside the files themselves. Where to look is a field — this folder, everywhere indexed, or a path — and a query line above the form is the same query seen twice, soreport ext:pdf size>10Mis the whole of it. - Preview with F3. Source code coloured for twenty-odd languages, Markdown
rendered, images, video paused at its first frame, CSV/TSV, SQLite databases and
Parquet files as a grid with filtering and copyable cells, and the bytes of
anything else. What a file is
comes from what is in it rather than from its name, so a
Dockerfileopens as a coloured Dockerfile. Every viewer has a details panel: a photograph's camera and exposure, a document's author, a video's codecs, an audio file's tags. A file of any size opens at once — only the part being shown is ever read. Left and right step through the folder. - Commander-style file operations. Copy and move between panes with F5/F6, across any two drives; rename, create and delete with F2/F7/F8.
- Dragging in and out. Files leave a listing by pointer into anything that takes files, and arrive the same way into the folder a pane is showing — always as a copy, asking before it overwrites a name. A row that is not on this computer is fetched first, so an archive and a bucket can be dragged out of too.
- Git state, read and never written. A folder inside a checkout says which branch, how far it is from what it tracks, what the last commit was and how much has changed; the rows carry git's own letters, and a folder says when something inside it has changed. Refreshed when an operation writes or when you commit from the terminal panel. Local drives, and it needs libgit2 — without it Mole behaves exactly as it did before. Mole shows git state and does not change it.
- Full keyboard control. Arrows, Enter, Insert to select, function keys for operations. Enter hands a file to the desktop's default application.
- Background everything. Listing, scanning and searching run on a thread pool with progress and cancellation. The UI thread never touches storage.
- A file index. Scan a tree once, then search it instantly without going back to the disk (or the network). A scan can also record what each file says about itself — a camera, an author, a duration — and list what is inside the archives it meets; the contents themselves are deliberately never indexed. A folder with an indexed subfolder is answered by both at once, and every row says whether it is what is on disk now or what a scan remembered. Re-scans keep what has not changed, and a folder can be put on a clock at any interval. The Indexes tab lists every index there is — how old each one is, what kind of scan built it, whether anything is keeping it fresh — and is where one is rescanned, stopped or thrown away.
- Thumbnails, and a gallery to put them in. Pictures, PDF first pages and video frames, made off the UI thread, a few at a time, only for what is on screen, and cached in memory and on disk. On a drive that is not local the thumbnail a camera wrote into the file is read instead of the file — kilobytes rather than megabytes — and anything past a ceiling is left alone.
- Sessions. Open tabs, their folders, their layout and the window's own size come back after a restart. Each tab kind decides what it remembers, plugins included.
- Drives and bookmarks. The sidebar lists what the machine actually has mounted — with how full each one is, amber past three quarters and red past nine tenths — plus the places you saved yourself. Drives with no meaningful capacity simply show a name.
- Directory reports. Analyse one folder or several, each with its own history, and diff any run against an earlier one.
- Jobs on a clock. Put a report on a repeat and it runs in the background,
including catching up on a run missed while the machine was off. A tracking
tab (
Ctrl+Shift+J) shows every attempt and puts failures first. - Sync between any two drives. Update, mirror or fill gaps, with filters and a dry run that is the real plan with the last step withheld.
- Duplicate detection. Four strategies, staged so the expensive comparison only ever sees what the cheap ones could not rule out.
- Bulk rename. Composable operations with a live preview, and a batch that would collide is refused rather than half-applied.
- File sets. A hand-built list of files across any number of drives that every operation accepts exactly as it accepts a selection.
- A terminal panel. A shell for the folder you are looking at, along the bottom of the window.
- Network drives. SFTP, FTP and FTPS, S3, WebDAV, SMB and NFS, each configured from a short form the backend itself describes. One S3 engine serves AWS, Backblaze B2, MinIO, Ceph, Wasabi and R2 — the endpoint and the addressing style are just fields. A Windows or NAS share and an NFS export are reached in-application, with no mount and no root. They ship as a loadable plugin, and further backends arrive the same way.
- Credentials encrypted and portable. Passwords live in an AES-256-GCM store
keyed by a passphrase you choose, never in the settings file. It is not tied to
this machine: back up the configuration and the same passphrase opens it on a
fresh install. The encryption is what protects the file at rest on every
platform; on Unix it is
0600as well, and on Windows it is whatever ACL the file inherits from your profile directory, which Qt cannot narrow further. - A plugin API with a loadable-shared-library path, used by the shipped archive and network plugins.
Requires a C++20 compiler, CMake 3.24+ and Qt 6.4+.
On Ubuntu 24.04:
sudo apt install -y build-essential ninja-build ccache pkg-config git \
qt6-base-dev qt6-base-dev-tools qt6-declarative-dev qt6-declarative-dev-tools \
qt6-tools-dev qt6-tools-dev-tools qt6-svg-dev libqt6sql6-sqlite \
qml6-module-qtquick qml6-module-qtquick-controls qml6-module-qtquick-layouts \
qml6-module-qtquick-templates qml6-module-qtquick-window \
qml6-module-qtqml-workerscript qml6-module-qtquick-shapes \
libarchive-dev libcurl4-openssl-dev libssl-dev
make build # binary lands in build/debug/mole
make run
make testOptional but recommended while developing:
sudo apt install -y clang-format clang-tidy cppcheck valgrindccache is optional too, and nothing asks for it: the build looks for it and uses
it when it is there. It used to be named in the base preset, which made a machine
without it fail to configure at all.
libarchive-dev is optional: without it the archive plugin is skipped and the
rest of the application builds normally. The same goes for libcurl4-openssl-dev
and libssl-dev, without which the network plugin is skipped and there are no
SFTP, FTP, S3 or WebDAV drives — configure says so, rather than offering drives
that cannot connect. libsmbclient-dev and libnfs-dev are optional in the same
way and one step finer: without either, the plugin still ships and only that drive
kind is missing, which configure names.
make build already produces one at build/debug/mole, but it is a
debug build that only runs from the build tree. For anything else:
make optimised # optimised, still run from build/release/
make install # into /usr/local — override with PREFIX=~/.local
make bundle # self-contained folder in dist/, runs without Qt installed
make packages # a .deb, an .rpm and an AppImage, each for the family it installs on| Download | On disk | Needs Qt on the target | What it cannot do | Use it for | |
|---|---|---|---|---|---|
make optimised |
— | 127 MB | yes | — | running on this machine |
make install |
— | 196 MB | yes | — | your own machine |
.deb |
3.7 MB | 10 MB | yes, from the archive | no Parquet grid | Debian and Ubuntu |
.rpm |
2.5 MB | 11 MB | yes, from the archive | — | Fedora and RHEL |
tarball (make bundle) |
79 MB | 209 MB | no | video needs the host's ffmpeg | handing it to someone else |
| AppImage | 110 MB | 294 MB | no | no Parquet grid; video needs the host's ffmpeg | any distribution from 2021 onwards — it runs on glibc 2.34 and upwards |
Where those figures come from, because a size is not a property of the program.
Measured on 2026-09-01 from the artefacts the release workflow builds, against Qt
6.4 on Ubuntu 24.04 — except the .rpm, built on Fedora 40, and the AppImage, built
on AlmaLinux 9 for the glibc floor (see TODO.md). MB means 10⁶ bytes; on disk is
the apparent size of the unpacked tree, which is what your filesystem has to hold.
The tarball moved twice on 2026-09-01 and ended smaller than it started: up by
about 85 MB when it gained a media backend it had never had, then down by 80 when the
whole codec stack was left to the host for the licence reason under Video previews
below. The AppImage row is from a build of the same day; it was never carrying the
Ubuntu codec closure, so it did not shrink the same way.
A build finds what a machine has, so yours will differ: leaving Arrow out takes tens
of megabytes off, and the two figures for make optimised and make install are
large because neither strips debug information — the packages, the tarball and the
AppImage all do.
The AppImage's row carries the one promise that is not about size: it runs on
glibc 2.34 — Ubuntu 22.04, Debian 12, RHEL 9 and anything newer — because that is
what it was built on, and an AppImage cannot carry the C library it links. Built on
something newer it would refuse to start on everything older, with a GLIBC_2.39 not found that reads like a corrupt download. TODO.md records why that floor and not
another, and the release checks both ends of it every time.
What it cannot do is the column to read before choosing — and the rule behind
that column is the same everywhere: a preview whose library is missing falls back
to the file-information view. You get what Mole can say about the file without
reading it — its size, type and dates — rather than an error, an empty pane or a
crash. mole --plugins says which libraries it found, so a preview that is not
what you expected has an answer rather than a guess.
Every artefact browses archives, opens the network drives, renders PDFs, shows git state and keeps its credential store encrypted. The two differences worth knowing about are below, and both are libraries you can install yourself.
A .parquet file opens as a grid with filtering and copyable cells where Apache
Arrow is available, and as the file-information view where it is not.
libarrow is in no Debian or Ubuntu archive today — not in Debian 12 or 13, not
in Ubuntu 24.04 or 25.04 — so the .deb is built without it, and so is the AppImage,
whose build host has only Arrow 9 and the code needs newer. Fedora packages Arrow and
Parquet, so the .rpm has the grid; the tarball carries its own copy and answers to
nobody's archive.
If you want the grid on Debian or Ubuntu, install Arrow from the project's own
packages — https://arrow.apache.org/install/ — and use the tarball, which is the
artefact built against it. Ubuntu 26.04 carries Arrow 23 in the archive, and from
there the .deb can have the grid without anything extra.
A video shows a frame from it, and a folder of videos shows a tile for each, where
the host has the decoders. Where it has not, both fall back to the
file-information view, and mole --plugins says backend found: none that will load.
The tarball and the AppImage deliberately do not carry ffmpeg. A
distribution's ffmpeg is built against whatever that distribution is willing to
ship, and on Ubuntu that includes libx264, libx265, libxvidcore and libzvbi
— GPL-2+ every one — while the AlmaLinux build the AppImage comes from adds
libfdk-aac, which is not free software at all. Mole is Apache-2.0, so a
self-contained artefact carrying any of them would be one nobody could
redistribute. What Mole carries is decided here rather than by somebody's packaging
policy, so the whole codec stack is the host's.
Qt's ffmpeg plugin is in both artefacts — it is LGPL, like the rest of Qt. It loads where the host has the libraries and does not where it has not. On any desktop that plays video they are already installed. Where they are not:
| Debian, Ubuntu | sudo apt install libavcodec60 libavformat60 libswscale7 — or ffmpeg, which pulls all of them |
| Fedora | sudo dnf install ffmpeg-libs (RPM Fusion free) |
| Arch | sudo pacman -S ffmpeg |
| openSUSE | sudo zypper install ffmpeg-4 |
The Debian sonames move between releases; apt search libavcodec names the one that
release has, and installing ffmpeg is the version-proof way. The .deb and .rpm
need none of this — they depend on the distribution's own ffmpeg, which arrives with
whatever it was built against.
make install lays out <prefix>/bin/mole and
<prefix>/lib/mole/plugins, plus a desktop entry and icon so the
app shows up in the launcher. The binary finds its plugins relative to itself,
so any prefix works without rebuilding.
make bundle additionally copies Qt, the platform plugin, the SQLite driver
and the QML modules into dist/, behind a launcher script that points Qt at
them. Ship the whole dist/ folder; the entry point is dist/mole.
Check a packaged build without a display:
./dist/mole --plugins # prints the search path, what loaded, and the media stack
./dist/mole --diagnostics # the same thing, under the name the code calls itMole is in no distribution's archive, so nothing updates it for you and nothing would otherwise ever mention that a new version exists. So when it starts, Mole asks once whether it is out of date. That is on by default, and Help → Check for new versions turns it off.
What leaves your machine is one GET of one file:
https://raw.githubusercontent.com/Ogefest/mole/main/latest.json
carrying these headers and nothing else:
Host: raw.githubusercontent.com
User-Agent: Mole
Accept-Language: en
If-None-Match: "<the tag GitHub gave for that file last time>"
Connection: Keep-Alive
Accept-Encoding: <whatever compression your Qt offers>
No install id, no counter, no platform, and no version number. Two of those
headers are set by Mole rather than left to Qt, and both for this reason. The user
agent says Mole and no more: a version there would be a count of installs per
release arriving at somebody else's server. And Accept-Language is fixed at en
because Qt builds that header out of your system locale — a default request would say
pl-PL,en,* on a Polish machine, which is the one thing in it that says anything
about who is asking. If-None-Match is GitHub's own tag for the file from the last
time it was read, which is what makes the ordinary answer 304 Not Modified with no
body at all. GitHub sees what it sees for any download from the repository, an
address and a time; Mole tells it nothing beyond that.
Nothing is downloaded and nothing is installed, ever. Mole names the version and offers to open its release page. Updating is whatever you did to install it.
You are told once per version, and then there is a week of quiet. If a notice is shown and you do nothing, Mole does not ask again — not even the question — for seven days, and a version you have already been told about is never announced a second time.
Failure is silent. No network, a captive portal, a proxy, a firewall, a server
error, an answer that stops half way: none of them produces a message, a line in the
session log above debug level, or a delay you would notice. A machine that cannot
reach GitHub behaves exactly like one that is up to date. MOLE_LOG=update mole says
what happened, if you want to know.
| Target | Does |
|---|---|
make build |
configure (if needed) and compile |
make run |
build and launch |
make install |
install into PREFIX (default /usr/local) |
make uninstall |
remove an installed copy |
make bundle |
self-contained folder in dist/ |
make test |
build and run the whole suite in parallel |
make asan |
build and test under AddressSanitizer + UBSan + leak detection |
make screenshots |
drive the real interface headlessly and photograph each verified state |
make guide-images |
the same, copied into the user guide |
make optimised |
optimised build with debug info |
make release |
cut a release: all three test tiers, version, changelog marker, commit, tag, push |
make format |
apply .clang-format across the tree |
make tidy |
run clang-tidy over the compilation database |
make help |
list all targets |
The Makefile is a thin wrapper over CMake presets, and it is GNU make with shell
recipes — which is not the way in on Windows. Nothing needs porting, because the
presets are the real build configuration and CMake drives them directly:
cmake --preset debug # make build, first half
cmake --build build/debug # make build, second half
ctest --test-dir build/debug --output-on-failure # make testbase fixes the generator to Ninja, which exists on all three systems. On Windows
that means running these from a developer command prompt, where the MSVC
environment has already been set — Ninja finds no compiler otherwise.
Ctrl+T / Ctrl+Shift+T |
new browser tab / new dual-pane tab |
Ctrl+W, Ctrl+Tab, Ctrl+1…9 |
close, cycle, jump to tab |
F4 |
open the application menu (arrows and Enter from there) |
| just start typing | filter this folder |
F3 |
preview the file under the cursor |
Ctrl+F / Ctrl+Shift+I |
search this folder / search everywhere indexed (new tab) |
Ctrl+Shift+C / Ctrl+Shift+F |
copy this folder's path / the selected file's path |
Ctrl+D |
bookmark this folder — or, in the Sets tab, the set you are looking at |
Ctrl+G or Ctrl+L |
type a destination in the path bar |
Ctrl+← / Ctrl+→ / Ctrl+↑ |
back / forward / up |
↑ ↓ PgUp PgDn Home End |
move the cursor |
Enter |
open — folder, archive as a drive, or the default application |
Backspace |
go up one folder |
Tab |
switch pane (dual mode) |
Insert / Space / Ctrl+A / * |
tick and advance / tick / select all / invert |
F2 F5 F6 F7 F8 |
rename, copy, move, new folder, delete |
The ⌨ button in the toolbar shows the same list in the app.
In the Sets tab the same keys do the same kind of thing to a set's members: the
arrows walk them, Enter opens the member itself in a browser with the cursor already
on it, and F3 previews it without leaving the set. A member whose file has gone says
so rather than opening the folder it used to be in.
The first block works wherever the keyboard is; so do F3 and Ctrl+←/→/↑,
because what they act on is the pane in front of you rather than whatever holds
the keyboard. The rest need the listing focused — cursor keys, typing to filter
and ticking rows are about the thing you are looking at, and F2 F5 F6 F7
F8 need to know which pane they are working from. See
ADR-0019.
src/core VFS, tasks, event bus, index (headless, QtCore + QtSql)
src/sdk the published plugin API
src/host plugin loader and registries
src/ui list models and controllers (headless)
src/plugins built-in features + archive plugin
src/app main() and the QML shell
src/tools mole-tasks, the console runner (no GUI)
tests one binary per unit, plus an integration suite
tests/scripts the shell scripts, run against a stub ssh
docs/guide/— the user guide: browsing, previewing, searching, and the operations. Every picture in it was taken by the test suite immediately after asserting that what it shows is real, so it cannot document a feature that has stopped working.
mole-tasks runs any of the work without a window — for reproducing something
against a real server, for driving a transfer under tc netem, and for a machine
with no display. It reads the same drives, credentials and index the application
does. See ADR-0028.
mole-tasks copy --from file:///data/big.bin --to file:///backup --log net
mole-tasks sync --from file:///photos --to nas:///photos --mode mirror # says what it would do
mole-tasks sync --from file:///photos --to nas:///photos --mode mirror --apply
mole-tasks duplicates file:///downloads --by content
mole-tasks drives # what is mounted
mole-tasks help # every commandA drive that needs configuring comes from the store the application writes
(--drive «name», with the passphrase in MOLE_PASSPHRASE) or from the command
line (--mount name=nas,type=sftp,host=…,user=…,password=@SFTP_PASSWORD). A
value written @SOMETHING is read from that environment variable, so a password
stays out of the argument list and out of the shell history.
Exit codes: 0 done, 1 something in the work failed, 2 the command line is
wrong, 3 a drive could not be reached, 130 interrupted.
ARCHITECTURE.md— how the pieces fit and why.docs/WRITING_PLUGINS.md— adding a drive, a tab or a preview.
The extension points:
| To add | Implement |
|---|---|
| a drive (SFTP, S3, WebDAV, SMB, NFS, a git forge) | IFileSystemFactory + IFileSystem |
| a tab (duplicates, analytics, bulk rename) | IFeature + FeatureController |
| a viewer (PDF, SQLite, Parquet, bytes) | IPreviewProvider + PreviewController |
| what a file says about itself (EXIF, tags) | IMetadataReader |
| a menu entry under File / View / Tools / Help | MenuAction |
Built-in functionality is registered through the identical PluginRegistry
that third-party code uses, so the API cannot quietly rot.
| Variable | Effect |
|---|---|
MOLE_PLUGIN_PATH |
extra directories to search for plugins (:-separated) |
MOLE_INDEX_PATH |
where the SQLite index lives, instead of the user profile |
MOLE_SESSION_PATH |
where the open-tabs file lives, instead of the user profile |
MOLE_BOOKMARKS_PATH |
where the bookmarks file lives, instead of the user profile |
MOLE_ANALYSIS_PATH |
where saved reports live, instead of the user profile |
MOLE_SCHEDULE_PATH |
where the job schedule lives, instead of the user profile |
MOLE_CHAINS_PATH |
where saved chains live, instead of the user profile |
MOLE_ALERTS_PATH |
where watched metrics live, instead of the user profile |
MOLE_SETS_PATH |
where file sets live, instead of the user profile |
MOLE_SECRETS_PATH |
where encrypted credentials live, instead of the user profile |
MOLE_REMOTES_PATH |
where configured drives live, instead of the user profile |
MOLE_PLUGIN_PATH |
extra directories to load plugins from |
MOLE_LOG_PATH |
where the session log is written, instead of the user profile |
MOLE_STAGING_DIR |
where a payload is staged while it is written, instead of the temporary directory |
MOLE_UPDATE_MANIFEST |
where to ask what the newest release is, instead of the published manifest |
MOLE_LOG |
what to record in detail: task, drive, net, curl, update, or all |
MOLE_PASSPHRASE |
unlocks the credential store for mole-tasks, which has nobody to ask |
MOLE_SCREENSHOT_DIR |
where tst_Walkthrough writes its pictures |
Every run writes a session log next to the rest of the profile, keeping the previous
run alongside it, and a crash puts its backtrace in the same file. It records what
the application said, which for an operation that misbehaved is usually not enough —
so MOLE_LOG turns up the detail by subject, into the same file:
MOLE_LOG=net,curl mole # every network transfer, and libcurl's own account of it
MOLE_LOG=task,drive mole # what every job did, and every operation on every drive
MOLE_LOG=update mole # whether it looked for a newer release, and what it decided
MOLE_LOG=all mole # all of themtask and drive are written in one place each and so cover every job and every
drive, including ones a plugin brings. Credentials in header lines are redacted: a
log is a thing people send to each other.
The network backends carry conformance tests that talk to an actual server, and
they skip themselves when there is nothing to talk to — so make test is green on
a machine with no account, and no credential is ever committed. To run them, put
an account in the environment:
export MOLE_TEST_SFTP_HOST=… MOLE_TEST_SFTP_USER=… MOLE_TEST_SFTP_PASS=…
export MOLE_TEST_FTP_HOST=… MOLE_TEST_FTP_USER=… MOLE_TEST_FTP_PASS=…
export MOLE_TEST_S3_KEY_ID=… MOLE_TEST_S3_SECRET=… MOLE_TEST_S3_BUCKET=…
export MOLE_TEST_S3_REGION=… MOLE_TEST_S3_ENDPOINT=…
export MOLE_TEST_WEBDAV_URL=… MOLE_TEST_WEBDAV_USER=… MOLE_TEST_WEBDAV_PASS=…
make testOne thing to know before running them that way, because the failure does not look
like what it is. Those suites run under CTest's 180-second limit like everything
else in make test, and a conformance suite against a real server over a real link
exceeds it — tst_SftpFileSystem does. What you see is a suite killed part way,
which reads as a flaky test rather than as a limit being hit. Raise it for the run:
ctest --test-dir build/debug --timeout 900 -R 'FileSystem' --output-on-failureor run the suite's binary directly, which is what the project's own live tier does
— scripts/testbed/test-live.sh runs each one as its own process for exactly this
reason, and reports a suite that skipped as not green, because a suite that never
met the server is not a pass.
Each suite works under a uniquely named directory or key prefix and removes it
afterwards, so it is safe to point at a bucket or share that holds real files.
MOLE_TEST_SFTP_BASE, MOLE_TEST_FTP_BASE and MOLE_TEST_FTP_PORT override where
it works and how it connects. Use a throwaway account: these are test credentials
in a shell history.
One more of the same shape, and it is a path rather than an account.
MOLE_TEST_SNAPSHOT_PATH points at a folder inside a filesystem that exposes its
snapshots — set it and tst_LocalSnapshots checks that a real snapshot directory
behaves like the ordinary directory the whole feature assumes it is. Everything
else about earlier versions is held against a temporary tree in the same shape, so
the suite is green on a machine that has never taken a snapshot.
make test-heavy is the same thing at a size that hurts: gigabytes each way,
between local disk and every configured backend, with the payload verified byte
for byte against what belongs at each offset. It asserts more than "the copy
worked" —
- peak temporary space, which is the check that would have caught staging before it became a wall (see ADR-0014); a copy that streams needs room for a chunk, one that stages needs room for the whole file, and nothing else tells them apart
- resident memory and file descriptors, so a leak shows up here rather than after eight hours of somebody's backup
- throughput per run, recorded to a file, so a regression in speed is as visible as one in correctness
It asks the test machine how much room each destination has rather than being
told, and a destination that cannot hold the payload is a skip with the
reason — filling a test machine's disk would take every other suite down with
it. MOLE_TEST_HEAVY_BYTES sets the size; the default is 10 GiB.
The SFTP and S3 suites also carry large-file tests, because that is where transfers
break and a few kilobytes prove nothing. SFTP puts 64 MB on the server and reads it
back; MOLE_TEST_SFTP_LARGE_MB changes the size, and MOLE_TEST_SFTP_LARGE_PATH
points it at a file that is already there, which writes nothing at all. S3 writes an
object past the part size so the upload is a multipart one, sized by
MOLE_TEST_S3_LARGE_MB.
Backends: SFTP, FTP, S3, WebDAV, SMB and NFS all ship today. Google Drive, Dropbox
and OneDrive speak proprietary APIs and would each need a plugin of their own — see
ADR-0011.
Previews: DuckDB tables. PDF, SQLite, Parquet and video playback are done; so are
image metadata and audio tags, which read a header rather than linking exiv2 or
taglib — a reader is handed a bounded prefix of a file that may be on a remote
drive, and neither library works that way. See
ADR-0034.
Cross-platform: Mole is written to be portable, but it has only ever been configured, built and run on Linux. The platform-specific pieces found so far are being worked through; see TODO.md for where that stands.
Apache-2.0 — see LICENSE.
Qt is used under the LGPL-3.0, dynamically linked and unmodified. Plugins may be released under any licence their author prefers.
make licence-check verifies the conditions that make this combination valid;
docs/LICENSING.md explains each one and what you still
have to do when publishing a build. Third-party components are listed in
THIRD-PARTY-NOTICES.md.