A personal desktop work-log client (Flutter + Rust core, macOS / Linux / Windows).
中文文档:README_cn.md
Implemented based on the design in DESIGN.md.
- Quick notes: global hotkey (default
Ctrl/Cmd+Shift+L) pops up a small window anytime; press Enter to save - Auto collection: GitLab/GitHub commits, directory file changes, and meeting audio transcripts collected automatically; per code instance you can pick which repositories' commits are merged into the daily report (issue #31)
- AI summarization: dynamic provider list (Claude / DeepSeek / Ollama / OpenAI-compatible; cc-switch-style "add provider" flow, issue #25) with automatic fallback; the add-provider dialog can fetch the model list via the provider's official API and pick from a dropdown (issue #27)
- Auto update: checks for new releases at startup, downloads in the background and notifies; the update completes automatically on app restart
- About section: settings page shows version, build time, OS and other diagnostics with one-click copy for bug reports
- Pure Markdown storage:
日报/周报/月报/inbox/are all.mdfiles
<log root directory>/
├── 日报/2026-08-11-工作日报.md # finalized daily report
├── 周报/2026-W33-工作周报.md
├── 月报/2026-08-工作月报.md
├── inbox/2026-08-11.md # today's quick notes (append)
├── 转写/<meeting>_转写.txt # audio transcript cache
└── .daymark/
├── settings.json # config (tokens stored in system keychain)
├── 素材缓存/<date>.json # per-date collection cache
└── 草稿/<date>.md # unfinalized drafts
- Flutter (≥3.24, desktop platforms)
- Rust stable (cargo)
flutter_rust_bridge_codegen(cargo install flutter_rust_bridge_codegen)- Linux extras:
libayatana-appindicator3-dev(tray_manager),libsecret-1-dev,ninja-build,clang,cmake,pkg-config
# Generate FFI bindings (run after modifying rust/src/api/)
flutter_rust_bridge_codegen generate
# Rust tests
cd rust && cargo test
# Dart tests
flutter test
# Build
flutter build linux --release
# Package installers
./scripts/build_appimage.sh # Linux AppImage (hand-written AppDir + appimagetool)
./scripts/sign_macos.sh # macOS build + ad-hoc signing (dmg via CI)
powershell -File scripts/build_windows_installer.ps1 # Windows exe installer (NSIS)UI layer (Flutter) main window / hotkey popup / settings page / tray
Application layer (Dart) SettingsService / RecordService / CollectService / ReportService
Domain layer (Dart) material models / LLM adapters / transcription engine / report engine
Infrastructure (Rust core) document parsing (pptx/xlsx/docx/pdf) / file watching (notify) / global hotkey (global-hotkey)
The Rust core is bound to Dart bidirectionally via flutter_rust_bridge v2 FFI; events (hotkey triggers, file changes) are delivered to Dart via Stream callbacks.
For personal use (ad-hoc signing, no developer certificate needed):
flutter build macos --release
./scripts/sign_macos.sh # ad-hoc by default
open build/macos/Build/Products/Release/daymark.appFirst launch requires right-click → "Open" (ad-hoc signatures do not pass Gatekeeper; trusted locally only).
For external distribution (requires an Apple Developer account): sign with a developer certificate + notarization, see the header comments in scripts/sign_macos.sh.
GitLab CI (.gitlab-ci.yml): runs fully on every push —
| Job | Artifact |
|---|---|
rust-test / dart-test |
Rust core and Flutter tests |
prepare-version |
computes release version (latest GitLab releases tag patch+1) and generates auto-update dart-defines (passed to build jobs via dotenv) |
linux-build |
Linux AppImage installer (scripts/build_appimage.sh) |
macos-build |
macOS arm64 dmg (ad-hoc signed, runner: mac) |
windows-build |
Windows exe installer (NSIS, runner: windows) |
push-to-github |
syncs source to GitHub on every main push (excludes .gitlab-ci.yml, scripts/sync_github.py) |
publish-release |
publishes three-platform releases after all jobs succeed (full archive on GitLab + rolling 5 on GitHub, scripts/publish_release.py) |
Artifacts are uploaded as GitLab CI artifacts (retained 30 days). macOS notarization requires a developer certificate; CI only does ad-hoc signing by default (trusted locally).
GitHub source sync: after every push to main, the source is synced automatically to the public GitHub repository CodeFuckee/daymark, with .gitlab-ci.yml redacted (GitHub uses its own Actions workflow). The sync goes through the GitHub REST API (scripts/sync_github.py; the github.com git endpoint suffers intermittent SNI interference in mainland networks, making git push unreliable). Authentication requires the GitLab CI variable GITHUB_TOKEN (GitHub PAT with Contents: write / repo API permissions); this job is independent of the three platform builds (needs: []), so a build failure does not block the sync and vice versa.
GitHub Actions (.github/workflows/build.yml): triggered on v* tags or manually; matrix builds on three platforms (Linux tar.gz / macOS dmg / Windows zip); artifacts uploaded to GitHub Actions artifacts, suitable for external distribution. Tag-triggered runs inject the version (tag minus v) and the GitHub update source (detection URL = GitHub releases of CodeFuckee/daymark).
Mechanism: update source addresses are baked into the app at packaging time via --dart-define (build-time injection, read-only at runtime). GitLab CI packaging → checks GitLab repository releases (prepare-version job generates DAYMARK_UPDATE_SOURCES_B64, scripts/update_defines.py); GitHub Actions packaging → checks GitHub repository releases. When both are injected, the highest version wins.
Flow: background check at startup (or when "Check for updates" is clicked) → auto download (sha256 verification, asset digest for GitHub releases) → when the download completes a dialog pops up automatically asking the user to restart now or later ("Restart later" keeps the manual "Restart & update" button on the settings page) → update completes automatically when the app restarts:
- Linux: new AppImage atomically replaces the file
$APPIMAGEpoints to → launches the new version - macOS: mounts the dmg →
dittooverwritesDaymark.app→ clears quarantine → launches the new version - Windows: launches the NSIS installer with
/S /UPDATEfor silent overwrite install and auto-start of the new version
Update packages are cached in <app support dir>/update/ (manifest.json + installer) and installed by main() on restart. When a download completes, a "Restart now / Restart later" dialog pops up automatically (a single completed download only prompts once; a later re-check with another completed download prompts again; the window switches back to the main-window form so the dialog is visible even in quick-note mode or when hidden to the tray). The settings page has "Check for updates / Restart & update" buttons, the tray menu has "Check for updates", and the "check at startup" toggle can be disabled in settings. Local dev builds (no update source injected) have the whole update feature disabled.
Version consistency: release versions are computed by scripts/next_version.py (latest GitLab releases tag patch+1); build artifacts embed the same version via --build-name, and publish-release publishes the same tag — artifact versions strictly match release tags, and update detection compares semver.
Public repository anonymous access: daymark's GitLab repository is public (confirmed by the user in issue #5); update detection (releases API) and artifact downloads (generic packages) are all anonymous, and no token is embedded in artifacts. The historically configured CI variable GITLAB_READ_API_TOKEN is no longer read and can be deleted. If the repository ever goes back to private, the token injection mechanism must be restored.
- Linux global hotkey depends on X11 (may not work under Wayland)
- The transcription endpoint is OpenAI-compatible (Groq / Volcano / Qwen all work; configure base_url)
- Cloud-synced directory mtime refreshes can cause false positives; daily reports use the wording "changes detected today". Historical-date rescanning attributes files to natural days by disk mtime — for a file modified on the target day and modified again later (mtime overwritten), files inside git repositories are recovered from git history (issue #32), while non-git files cannot be recovered (generate the daily report on the day itself, or use quick notes for important changes, when the app was not running that day)
- Auto update only applies to installer-form artifacts (AppImage / dmg install / NSIS install); GitHub Actions tar.gz / zip artifacts are not auto-installable — download them manually after a new version is detected
Contributions are welcome! See CONTRIBUTING.md for issue reporting, the development workflow, commit conventions, and test requirements.
This project is licensed under the MIT License.