This file is for coding agents working in this repository. It explains the current product behavior, repository structure, architecture rules, and release workflow so another agent can continue work without rediscovering context.
Trayffeine is a Windows system tray application that keeps the machine awake while a session is active.
Current product behavior:
- no main window
- active and inactive tray icons, including a pressed-looking active state
- presets:
15m,30m,1h,2h,infinite - timed sessions automatically return the app to inactive mode
- one notification when a timed session ends
- tray tooltip shows live elapsed and remaining time
- double-click on the tray icon toggles infinite mode
- single-instance guard on Windows
- runtime localization for
pt-BR,en, andes - persistent language selection
- persistent keep-awake method selection
- supported keep-awake methods:
smart,execution-state,f15,shift - persistent
Start with Windowstoggle - persistent detailed logging toggle
- persistent presence compatibility toggle that uses
F15as the effective method - configured and effective keep-awake method summaries in the tray menu
- support actions for help, opening logs, and clearing logs
- support action for copying diagnostics
- persistent restore of infinite mode, while timed sessions always restart inactive
- first launch defaults to infinite restore plus detailed logging enabled
- per-user installer that always creates a Start Menu shortcut
- future Store preparation through an isolated MSIX preflight package; it is not a published channel yet
- Development and editing can happen in Windows or WSL.
- Official Windows installers are built in GitHub Actions on
windows-latest. - Do not treat WSL as the place to produce final Windows distributables for users.
- Python target is
3.13.
Recommended local loop:
python3.13 -m venv .venv
. .venv/bin/activate
python -m pip install -e .[dev]
python scripts/generate_assets.py
ruff check .
pytestFor real tray validation, run the app from a real Windows path.
-
src/trayffeine/app.py- runtime bootstrap
- settings load
- effective log-level selection
- single-instance guard
- crash boundary
- tray/service wiring
-
src/trayffeine/app_logging.py- rotating log configuration
- env override handling
- runtime log-level switching
- log cleanup helpers
-
src/trayffeine/service.py- background worker loop
- keep-awake cadence
- backend lifecycle
- timer expiration
- callback dispatch for state changes, timer completion, and tooltip ticks
-
src/trayffeine/session.py- pure session state and timing math
- stable preset keys only
-
src/trayffeine/keepawake.py- stable keep-awake method ids
- coercion helper for persisted settings
- effective-method selection for presence compatibility
-
src/trayffeine/presenter.py- tray summaries
- tooltip text
- notification payloads
- presentation-only text assembly
-
src/trayffeine/diagnostics.py- stable support diagnostics text assembly
-
src/trayffeine/i18n.py- locale detection and normalization
- runtime catalogs
- language selection model
-
src/trayffeine/tray.py- pystray integration
- grouped menu construction
- support actions
- tooltip refresh and icon/menu refresh behavior
- notification dispatch
-
src/trayffeine/settings.py- JSON settings persistence
- stores language, infinite restore, detailed logging, keep-awake method, presence compatibility, and startup preference
- missing settings file is treated as first launch
-
src/trayffeine/win32_tray.py- Windows-specific tray wrapper
- intercepts tray double-click without breaking right-click behavior
-
src/trayffeine/windows.py- Windows keep-awake backends
SendInputkeyboard backends forF15andShiftSetThreadExecutionStatebackend- smart fallback backend
- mutex
- dialogs
- shell-open helper
- clipboard helper for diagnostics
- channel-aware startup registration:
Runkey for the EXE install and startup task for MSIX
-
packaging/windows/trayffeine.spec: PyInstaller bundle definitionbuild.ps1: manual packaging entrypointTrayffeine.iss: Inno Setup installer script
-
packaging/msix/AppxManifest.xml.template: Store identity placeholders, full-trust entry point, and startup taskbuild.ps1: isolated unsigned MSIX preflight builder using MakeAppxREADME.md: short pointer to the full Store-preparation procedure
-
tests/- unit and smoke-style coverage for session, presenter, i18n, logging, tray wiring, service behavior, and Windows integration helpers
-
CHANGELOG.md- milestone summary through
1.2.0
- milestone summary through
-
Keep state and presentation separate.
session.pyowns keys and time math.- localized text belongs in
i18n.pyandpresenter.py.
-
Do not hardcode user-facing runtime text in
tray.pyorapp.py.- tray labels, dialogs, tooltips, and notifications should go through the translator.
-
Preserve stable preset keys.
15m,30m,1h,2h,infinite- these are internal contracts and should not be translated
-
Preserve stable keep-awake method ids.
smart,execution-state,f15,shift
-
Keep presence compatibility separate from keep-awake method ids.
- it is a persisted preference
- while enabled, the effective backend is
f15 - the saved normal keep-awake method must remain unchanged
-
Keep backend lifecycle on the worker thread.
SetThreadExecutionStatemust be started, refreshed, and cleared on the same worker thread
-
Prefer stable tray menu summaries.
- the menu should not depend on live-refresh while open
- live counters belong in the tooltip, not in the open menu
- per-second tick refreshes should update only what is necessary
-
English is the fallback language.
- missing or unsupported locale resolution should still produce English text
-
Keep correct accents and natural spelling in localized text.
-
Do not promise Teams or other app-presence status.
- describe presence compatibility as best effort
- preserve the distinction between preventing Windows idle/sleep and influencing app-specific presence
-
Keep diagnostics plain and stable.
- the clipboard payload is support text, not localized UI copy
- include version, language, session, methods, key preferences, settings path, and log path
-
Keep startup integration channel-aware.
- the EXE/Inno Setup/WinGet install must keep its current-user
Runkey behavior - an MSIX package must use its declared
TrayffeineStartupstartup task, not a virtualizedRunkey - do not try to override a startup task that the user disabled in Task Manager
- the EXE/Inno Setup/WinGet install must keep its current-user
Stored settings currently include:
- language selection
restore_infinitedetailed_logging_enabledkeepawake_methodpresence_compatibility_enabledstart_with_windows
Current first-run defaults:
restore_infinite = truedetailed_logging_enabled = truekeepawake_method = smartpresence_compatibility_enabled = falsestart_with_windows = falselanguage_selection = auto
Timed sessions must never resume after restart.
Current log file:
%LOCALAPPDATA%\Trayffeine\logs\trayffeine.log
Rotation defaults:
256 KB3backups
Logging policy:
- default runtime level is
WARNING - detailed logging maps to
INFO - meaningful lifecycle and user actions may be logged at
INFO - high-frequency internal events must not be logged at
INFO
Examples of useful INFO events:
- app start and exit
- preset selection
- infinite mode enable or disable
- language change
- keep-awake method change
- presence compatibility toggle
- start-with-Windows toggle
- timer expiration
- opening logs folder
- toggling detailed logging
- clearing logs
When changing logging:
- do not duplicate root handlers
- keep
TRAYFFEINE_LOG_LEVELprecedence intact - if logs are cleared, recreate the current file immediately
- Installation is per-user under
%LocalAppData%\Programs\Trayffeine. - The installer always creates a current-user Start Menu shortcut.
- The installer is unsigned.
- Installer changes belong in
packaging/windows/Trayffeine.iss. - Keep the release workflow Windows-only for installer generation.
- Keep the MSIX preflight workflow separate from tags, GitHub Releases, and WinGet updates.
- Keep all GitHub Actions references pinned to reviewed full commit SHAs.
- Distributable builds must install from the checked-in hash-locked requirements files.
- Release tags must cross into PowerShell as environment data and pass the strict release-tag validator before build or publication.
- Keep artifact construction read-only and keep credentialed GitHub Release/WinGet publication
behind the protected
releaseGitHub Environment. - Keep external installer and WinGet tooling fixed by version and verified by digest and expected Authenticode signer before execution.
Before considering work complete, run:
. .venv/bin/activate
ruff check .
pytestWhat tests do not guarantee:
- real interactive tray behavior on Windows
- actual Windows notification rendering
- full packaged runtime behavior on an end-user desktop
For changes touching pystray, dialogs, or installer behavior, the final confidence step is still a real Windows run.
- Project version is currently
1.2.0. - Runtime version lives in:
pyproject.tomlsrc/trayffeine/__init__.pypackaging/windows/build.ps1packaging/windows/Trayffeine.iss
GitHub workflows:
CIruns on push tomainand on pull requestsPreview Buildruns on pull requests and manual dispatch, publishing a Windows installer artifact for testingMSIX Preview Buildruns on relevant pull requests and manual dispatch, publishing only an unsigned preflight artifactReleaseruns only on tagsv*- stable tags such as
v1.2.0publish normal releases - tags matching
v*-beta*publish GitHub prereleases
If changing packaging or release behavior, verify:
- tag pushes do not trigger redundant CI runs
- the Windows workflow still publishes the installer to the GitHub release
- the release workflow still publishes through
gh
- No signing pipeline is integrated yet.
- SmartScreen reputation is not solved in the current repo state.
- Installer localization is still separate from runtime localization.
- The app is Windows-only at runtime even though development may happen in Windows or WSL.
- Teams or similar presence behavior is not guaranteed by the keep-awake methods.
- If the task is UI text, start in
i18n.pyandpresenter.py. - If the task is timing or keep-awake behavior, start in
service.py,session.py, andwindows.py. - If the task is tray/menu behavior, start in
tray.pyandwin32_tray.py. - If the task is logging behavior, start in
app_logging.pyandapp.py. - If the task is packaging or release behavior, start in
packaging/windows/and.github/workflows/. - Do not remove the Windows validation caveats from the docs unless the behavior has actually been tested on Windows.