The document had drifted well past the point of being useful as an index: it listed 130 tests against 170 in the tree, described four test files that were never added to it at all (domain/config_test.go, runner/seed_test.go, ui/layout_test.go, ui/theme_test.go), attributed runner's Windows invocation tests to the wrong file, kept two tests that no longer exist (TestParseRegistryRunValue, TestLinuxAutostartRemovesLegacyDesktopEntry), and filed three activity-panel tests under jobs_view_test.go when they live in history_view_test.go. Most of the gap is the work of the last few releases: the per-job timeout's three states, the persisted pause and jobs-list density, SeedStats, and the whole GUI-geometry set the layout review produced. Three claims were false rather than merely missing. The ui test files are no longer "pure helpers, no Fyne widget construction" — they build views under test.NewApp() and measure them, which is now stated as its own design principle, because that measurement is what makes the STANDARDS rule about theme-derived sizes enforceable. layout.go is no longer an open coverage gap. And the coverage-gap list now names the real remaining one: Fyne's headless driver cannot report a maximized window, which is the reason window-size persistence is frozen. Verified mechanically: every test function in the tree appears exactly once in the document, under the file it actually lives in, and the document names no test that does not exist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
GoSentry
GoSentry is a cross-platform desktop scheduler. It provides a native GUI for creating, grouping, pausing, running, and monitoring scheduled shell commands.
Screenshots
Jobs tab — job list with details panel and run statistics. |
Settings tab — application, queue, storage, and version info. |
Features
- Native desktop GUI built with Fyne.
- Job definitions stored in a clean, hand-editable
jobs.json. @everyintervals and standard 5-field cron expressions.- Manual and scheduled command runs.
- Parallel or sequential execution mode; configurable overlap policy (skip or queue).
- Per-run
.logfiles with stdout/stderr capture. - Log cleanup by maximum file count and maximum age.
- Global pause/resume for scheduled job execution (manual runs remain available).
- Desktop notifications on job failure.
- Windows tray icon: left-click to show the window, right-click for the menu.
- Autostart on login (Windows shortcut; Linux XDG desktop entry).
Platforms
GoSentry is built and tested on Windows and Linux:
| Platform | Status | Notes |
|---|---|---|
| Windows | Supported | Tray icon, autostart shortcut (.lnk), desktop integration. |
| Linux | Supported | Autostart via XDG desktop entry; desktop integration on X11/Wayland. |
| macOS | Not supported | The Fyne GUI may build, but autostart and desktop integration are not implemented. |
Documentation
- Changelog — record of notable changes by version
- Roadmap — planned work larger than a single bug fix
- Architecture — component interaction model
- Standards — quality rules and intentional behavior
- Review — what a whole-project review looks at
- Development — build instructions, project layout, dependencies
- Tests — test suite layout and how to run it
- Performance — measured performance findings
Storage
GoSentry stores its files next to the executable by default, making it a portable application: moving the program folder also moves its configuration.
gosentry.json stores application settings:
{
"jobs_file": "jobs.json",
"logs_dir": "logs",
"max_log_files": 100,
"max_log_age_days": 30,
"keep_running_in_tray": true,
"notify_on_failure": true,
"execution_mode": "parallel",
"overlap_policy": "skip"
}
jobs.json stores job definitions:
{
"jobs": [
{
"id": 1,
"name": "Hello scheduler",
"folder": "Examples",
"schedule": "@every 1m",
"command": "echo GoSentry test job: scheduler is alive",
"enabled": true
}
]
}
jobs_file is the file GoSentry reads job definitions from, file name included,
so the file can be named anything. The default "jobs.json" is relative and
resolves to the executable's folder. An absolute path can be used when jobs
should live elsewhere, such as a shared network drive.
A gosentry.json from an earlier version that carries jobs_dir instead keeps
working: the directory is combined with jobs.json on load, and the file is
rewritten with jobs_file.
logs_dir is relative to the program folder when it does not start with a
drive letter or /.
Command output is written to separate files under logs_dir. File names
include the run timestamp and job name:
20260614-224306_Hello_scheduler.log
Schedules
Interval schedules using Go duration syntax:
@every 10s
@every 5m
@every 1h30m
Standard 5-field cron expressions:
*/5 * * * * every five minutes
0 2 * * * every day at 02:00
30 9 * * 1-5 weekdays at 09:30
Using The App
- Start GoSentry.
- Use New job to create a scheduled command.
- Set Schedule, Command, optional Arguments, Folder, and Enabled.
- Use Run now for a one-off manual run without waiting for the schedule.
- Use Pause on a single job to suspend it without deleting it.
- Use Pause all as a global stop switch for all scheduled runs.
- Open History to see past runs, their trigger (
Manual,Schedule, orUI), state, and log file. - Open Settings to change the storage paths, log cleanup limits, queue behavior, and notifications.
The Jobs file row picks the file itself: Browse lists .json files, and
a path can also be typed to name a file that does not exist yet. What Save does
depends on whether that file is already there:
- The file exists — its jobs are loaded and replace the current list, so selecting a jobs file switches to it (another machine's file, a shared one on a network drive). History records how many jobs were loaded and from where.
- The file does not exist — the current jobs are written to it, which is how the jobs file is renamed or moved somewhere else.
Switching to a different jobs file is refused while a job is running, because loading a new list discards the run state of the old one.
The Start on login checkbox shows an OK or Problem status. Saving with
it enabled writes an autostart entry using the current executable path.
Autostart entries include --start-in-tray so scheduled jobs run after sign-in
without opening the main window.
Queue Settings
Two settings in the Queue group of the Settings tab control how simultaneous and overlapping runs are handled.
Execution mode — applies when multiple jobs become due at the same tick:
| Value | Behaviour |
|---|---|
parallel (default) |
All due jobs start at the same time. |
sequential |
Due jobs are started one after another, in the order they appear in the list. |
Overlap policy — applies when a job's next scheduled run fires while its previous run is still active:
| Value | Behaviour |
|---|---|
skip (default) |
The new run is discarded; the running instance continues. |
queue |
The new run is held and starts immediately after the current run finishes. |
Notifications
When Notify on failure is enabled in Settings, GoSentry sends a desktop notification whenever a scheduled or manual run exits with a non-zero exit code. The notification shows the job name and the exit code.
Autostart
GoSentry is a user desktop application, not a system daemon, so autostart is configured per user.
Linux:
# GoSentry writes an XDG Autostart desktop entry when Start on login is enabled.
~/.config/autostart/gosentry.desktop
[Desktop Entry]
Type=Application
Name=GoSentry
Exec=/opt/gosentry/gosentry-0.9.0-linux-amd64 --start-in-tray
Terminal=false
Windows:
# GoSentry writes a shortcut to the current user's Startup folder.
# A .lnk stores the executable path as TargetPath and --start-in-tray as
# Arguments, so paths with spaces do not need fragile command-line quoting.
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\GoSentry.lnk
Troubleshooting
Windows, VirtualBox, RDP, And OpenGL
GoSentry uses Fyne, and Fyne uses GLFW/OpenGL to create the desktop window. In a Windows virtual machine, especially when accessed through RDP inside VirtualBox, the available video driver can fail OpenGL initialization.
Typical error:
Fyne error: window creation error
Cause: APIUnavailable: WGL: The driver does not appear to support OpenGL
Known workaround:
- Download a Windows Mesa build from
mesa-dist-win. Use the
archive named like
mesa3d-<version>-release-mingw.7z— this matches the MSYS2 GCC toolchain used to build GoSentry. Thedevel,debug-info,tests, and checksum files are not needed. - Open the archive and use the
x64build. - Copy the Mesa OpenGL DLL files from
x64into the same directory as the GoSentry.exe:
dist\windows\
gosentry-0.9.0-windows-amd64.exe
opengl32.dll
...
Mesa's software OpenGL implementation lets the Fyne window start even when the VirtualBox/RDP driver does not provide usable OpenGL.
Development assistance
Parts of this project were developed with assistance from Cursor AI (Composer agent) and Claude Code.