Bump the version to 0.3.1 and record startup timing after the main window is actually shown. Keep autostart launches distinct in History by recording a separate tray-start message when the UI intentionally starts hidden.
GoSentry
GoSentry is a cross-platform desktop scheduler inspired by cron. It provides a native GUI for creating, grouping, pausing, running, and monitoring scheduled shell commands.
GoSentry is being designed and implemented with assistance from OpenAI Codex.
Project notes:
Features
- Native desktop GUI built with Fyne.
- Job storage in one clean YAML file.
- App settings in a separate YAML file.
@everyschedules and standard 5-field cron expressions.- Manual and scheduled command runs.
- Per-run
.logfiles with stdout/stderr. - Log cleanup by maximum file count and maximum age.
- Global pause/resume for all job execution.
- Windows tray support.
- Version shown in the window title, Settings, and build artifact names.
Requirements
Common:
- Go 1.22 or newer.
Windows:
- MSYS2 with UCRT64 GCC in
C:\msys64\ucrt64\bin.
Install these dependencies on Windows:
# 1. Install Go 1.22 or newer from https://go.dev/dl/.
# The default installer path is C:\Program Files\Go.
go version
# 2. Install MSYS2 from https://www.msys2.org/.
# Use the default installation path so UCRT64 tools are placed under
# C:\msys64\ucrt64\bin.
# 3. Open "MSYS2 UCRT64" from the Start menu and install GCC plus windres.
pacman -Syu
pacman -S --needed mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-binutils
# 4. In PowerShell, check that the compiler is available where the build script
# expects it. build-windows.bat prepends this directory automatically.
Test-Path C:\msys64\ucrt64\bin\gcc.exe
Test-Path C:\msys64\ucrt64\bin\windres.exe
Linux:
- A C compiler.
- Fyne native build dependencies, including OpenGL/X11 development packages.
On Debian/Ubuntu, the Linux dependencies are typically:
# Go builds the application, gcc is required by CGO/Fyne, and the OpenGL/X11
# development packages provide the native desktop headers used by Fyne.
sudo apt install golang gcc libgl1-mesa-dev xorg-dev
Build
Windows:
# Builds dist\windows\gosentry-<version>-windows-amd64.exe. The script changes
# to the repository root first, so double-clicking it from Explorer works. It
# also adds MSYS2 UCRT64 to PATH for this process only, embeds the Windows icon
# when windres is available, and uses the Windows GUI subsystem so no console
# window opens at startup.
.\scripts\build-windows.bat
The Windows build is created as a GUI application, so it does not open a terminal window.
The binary is written to:
# GUI executable produced by scripts\build-windows.bat.
dist\windows\gosentry-0.3.0-windows-amd64.exe
Linux:
# Make the helper executable once, then build a linux/amd64 Fyne binary.
chmod +x ./scripts/build-linux.sh
./scripts/build-linux.sh
The binary is written to:
# Linux executable produced by scripts/build-linux.sh.
dist/linux/gosentry-0.3.0-linux-amd64
Linux using Docker:
# Builds the Linux binary inside Docker using the versioned image tag
# gitea.mixdep.ru/mix/gosentry-builder:<version>. Useful from hosts or CI jobs
# where the native Linux/Fyne packages are not installed locally.
chmod +x ./scripts/build-linux-docker.sh
./scripts/build-linux-docker.sh
The binary is copied to:
# Linux executable copied out of the Docker build image.
dist\linux\gosentry-0.3.0-linux-amd64
Release build from Linux:
# Interactively choose Linux amd64, Linux arm64, Windows amd64, or all artifacts
# from one Linux/Docker workflow. The Dockerfile contains the builder
# environment; the build commands live in this script. Docker runs the build
# with the current user's UID/GID so dist/ files are not owned by root.
chmod +x ./scripts/build-release-linux.sh
./scripts/build-release-linux.sh
Non-interactive release builds can pass target names:
# Build only Linux arm64 and Windows amd64 artifacts.
./scripts/build-release-linux.sh linux-arm64 windows-amd64
The binaries are copied to:
# Linux artifact.
dist/linux/gosentry-0.3.0-linux-amd64
# Linux arm64 artifact.
dist/linux/gosentry-0.3.0-linux-arm64
# Windows artifact cross-compiled from Linux.
dist/windows/gosentry-0.3.0-windows-amd64.exe
Run From Source
Windows:
# Fyne requires CGO on Windows. MSYS2 UCRT64 provides the C compiler and native
# libraries used by the desktop backend.
$env:Path = 'C:\msys64\ucrt64\bin;' + $env:Path
$env:CGO_ENABLED = '1'
# go run starts the app from source. Use scripts\build-windows.bat when you need
# a standalone .exe without a console window.
& 'C:\Program Files\Go\bin\go.exe' run ./cmd/gosentry
Linux:
# CGO must stay enabled because the Fyne GUI links against native Linux desktop
# libraries.
CGO_ENABLED=1 go run ./cmd/gosentry
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 the session is opened 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
At: fyne.io/fyne/v2@v2.5.3/internal/driver/glfw/driver.go:149
Known workaround:
- Download a Windows Mesa build from
mesa-dist-win. For a
regular Windows x64 GoSentry build, use the archive named like
mesa3d-<version>-release-msvc.7z, for examplemesa3d-26.1.1-release-msvc.7z. Thedevel,debug-info,tests, and checksum files are not needed for this workaround. - Open the downloaded archive and use the
x64build from it. - Copy the Mesa OpenGL DLL files from
x64into the same directory as the GoSentry.exe, for example:
dist\windows\
gosentry-0.3.0-windows-amd64.exe
opengl32.dll
...
This makes Windows load Mesa's software OpenGL implementation next to the application binary, which lets the Fyne window start even when the VirtualBox/RDP driver does not provide usable OpenGL.
Storage
GoSentry creates its runtime files next to the executable by default.
gosentry.yaml stores application settings:
# Directory containing jobs.yaml. "." means "the folder where the GoSentry
# executable lives"; an absolute path can be used when jobs should live elsewhere.
jobs_dir: .
# Directory for per-run command output logs. Relative paths are resolved against
# the program folder, just like jobs_dir.
logs_dir: logs
# Keep at most this many .log files after cleanup. Newest logs are preserved.
max_log_files: 100
# Delete .log files older than this many days during cleanup.
max_log_age_days: 30
# Start GoSentry automatically when the current desktop user signs in.
start_on_login: false
# Closing the window hides it to the tray instead of stopping the scheduler.
keep_running_in_tray: true
# Reserved for desktop failure notifications; the setting is stored now so the
# UI and config format do not need to change when notifications are wired fully.
notify_on_failure: true
jobs.yaml stores only job definitions:
jobs:
# A harmless sample job created on first run so the scheduler can be tested
# immediately. Runtime fields such as last run time, next run time, and command
# output are intentionally not stored here; they are displayed in the GUI and
# written to separate log files.
- id: 1
# Human-readable name shown in the jobs list and used in log file names.
name: Hello scheduler
# Optional grouping label. Omit it or leave it empty to put the job under
# the "No folder" filter.
folder: Examples
# Either @every with a Go duration, or a standard five-field cron expression.
schedule: '@every 1m'
# Command passed to the platform shell: cmd.exe /C on Windows, sh -c on Linux.
command: echo GoSentry test job: scheduler is alive
# Disabled jobs remain in jobs.yaml but are skipped by the scheduler.
enabled: true
Command output is written to separate files under logs_dir. File names include the run timestamp and job name, for example:
# Format: YYYYMMDD-HHMMSS_<sanitized job name>.log
20260614-224306_Hello_scheduler.log
Schedules
Fast interval schedules:
# Go duration syntax after @every; useful for tests and simple intervals.
@every 10s
@every 5m
@every 1h30m
Standard 5-field cron schedules:
# Standard five-field cron: minute hour day-of-month month day-of-week.
*/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 jobto create a command. - Set
Schedule,Command, optionalFolder, andEnabled. - Use
Run nowfor a manual test run. - Use
Pauseto disable one job. - Use
Pause allas a global stop switch. - Open
Historyto see whether a run wasManual,Schedule, orUI. - Open
Settingsto changejobs_dir,logs_dir, and log cleanup limits. UseBrowseto choose directories.
Changing jobs_dir saves the current job list to the new directory.
The Start on login setting shows an OK or Problem status next to the checkbox. Saving settings with the checkbox enabled rewrites the autostart entry using the current executable path.
Autostart entries add --start-in-tray, so scheduled jobs begin running after sign-in without opening the main window.
Autostart
GoSentry is a user desktop application, not a system daemon, so autostart should be configured per user.
Linux:
# GoSentry writes an XDG Autostart desktop entry when Start on login is enabled.
# This is better for a GUI/tray application than a systemd user service because
# the desktop environment starts it inside the graphical user session.
# Saving the setting also removes the old ~/.config/systemd/user/pysentry.service
# unit if it was created by an earlier GoSentry build.
~/.config/autostart/gosentry.desktop
[Desktop Entry]
Type=Application
Name=GoSentry
Exec=/opt/gosentry/gosentry-0.3.0-linux-amd64 --start-in-tray
Terminal=false
Windows:
# GoSentry writes a shortcut to the current user's Startup folder when Start on
# login is enabled. A .lnk stores the executable path as a structured TargetPath,
# and stores --start-in-tray as Arguments, so paths with spaces do not need
# fragile command-line quoting. Saving settings rewrites the shortcut and removes
# old HKCU Run entries from earlier builds.
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\GoSentry.lnk
Project Layout
cmd/gosentrystarts the desktop app.src/guicontains the GUI.src/corecontains YAML storage, command execution, scheduling, and log cleanup.assetscontains app icons that are embedded into the application binary.scriptscontains build helpers.docscontains architecture notes, the changelog, and the roadmap.
Build outputs are written to dist/. The old local bin/ directory is not used.
Dependencies
GoSentry keeps the direct dependency list intentionally small:
fyne.io/fyne/v2for the native GUI.github.com/robfig/cron/v3for cron schedule parsing.go.yaml.in/yaml/v4for YAML settings and jobs.
The remaining entries in go.mod are indirect dependencies pulled by Fyne and the Go module resolver.
Source repositories for mirroring:
- Go toolchain: https://go.googlesource.com/go
- Fyne: https://github.com/fyne-io/fyne
- robfig/cron: https://github.com/robfig/cron
- yaml/go-yaml: https://github.com/yaml/go-yaml
To list every direct and indirect Go module used by the current checkout:
go list -m all