A minimal, distraction-free desktop app for daily journaling and task tracking — log what you did, capture todos, and let AI format your entries, all from a single text input.
CapLog is a chat-style daily log: type into one input and it becomes a Markdown journal entry or a todo (via slash commands). AI optionally cleans up each entry as you write. Everything is stored locally in SQLite.
There are plenty of note-taking apps and todo apps — but they're always separate. I used to write my todos on sticky notes and end up losing the sticky note. Nothing worked as a single suite that doubles as a quick daily log. CapLog exists to fill that gap: one place that helps you quickly journal your day and track your tasks together.
The outcome is a simple, quick app that stays open on your desktop, where you can quickly journal your daily work progress — so when you want to know what you did last week, it's all right there. AI is integrated into the flow: as you type your journal, it converts your text into bullets, shortens it, and fixes spelling mistakes.
This AI-powered work log and productivity app lets users quickly capture free-form notes that are automatically structured into organized log entries. It includes todo management with priorities and due dates, a chat-style activity feed, daily history tracking, and a monthly log view with export capabilities. A separate, undated Notes scratchpad is always available for plain-text scribbles that don't belong in the dated log, autosaving as you type. Users can easily browse and search archived entries through calendar-style navigation, manage historical data with safe deletion options, and export all logs and tasks to Markdown. The app supports optional AI formatting through OpenAI- or Anthropic-compatible backends while gracefully falling back to raw text when AI services are unavailable.
| Layer | Choice |
|---|---|
| Desktop shell | Tauri v2 |
| Frontend | React + TypeScript + Vite |
| State | TanStack Query |
| Storage | SQLite |
| Content | Markdown |
| Styling | Vanilla CSS |
| AI | Anthropic or OpenAI-compatible LLMs |
| Testing | Vitest + Testing Library + happy-dom |
| Package manager | pnpm |
| Input | Action |
|---|---|
any plain text |
Creates a log entry (AI-formatted if configured) |
/todo <task> |
Creates an open todo |
/todo <task> /by <date> |
Creates a todo with a deadline |
/important <task> |
Creates a high-priority todo |
/done <partial task text> |
Marks the first matching open todo as complete |
The header's 📝 Notes button opens a separate, undated scratchpad for plain-text scribbles — not part of the dated log, autosaves ~12s after you stop typing.
┌─────────────────────────────────────────────────────────┐
│ CapLog Desktop App │
│ │
│ ┌──────────┐ ┌──────────────────┐ ┌─────────────┐ │
│ │ Sidebar │ │ ChatArea │ │ TodoPanel │ │
│ │ │ │ │ │ │ │
│ │ Day list │ │ Log feed │ │ Important │ │
│ │ previews │ │ (chat-style) │ │ Due/Overdue │ │
│ │ stats │ │ │ │ Open │ │
│ │ │ │ ┌────────────┐ │ │ Comp. today │ │
│ │ │ │ │ ChatInput │ │ │ │ │
│ │ │ │ │ (textarea) │ │ │ │ │
│ └──────────┘ │ └────────────┘ │ └─────────────┘ │
│ └──────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ LogModal │ │ SettingsModal │ │ArchiveModal│ │ NotesModal │ │
│ │ (month log) │ │ (LLM config) │ │ (year view)│ │ (scratchpad│ │
│ └──────────────┘ └──────────────────┘ └────────────┘ └────────────┘ │
└─────────────────────────────────────────────────────────┘
│ Tauri IPC (invoke)
┌─────────────────────────────────────────────────────────┐
│ Rust Backend │
│ tauri-plugin-sql → SQLite (migrations auto-run) │
└─────────────────────────────────────────────────────────┘
flowchart TD
A([User types in textarea]) --> B[parseCommand\nsrc/commands.ts]
B --> C{Command type?}
C -->|plain text| D[type: log]
C -->|/todo /by| E[type: todo]
C -->|/important| F[type: important]
C -->|/done| G[type: done]
D --> H[getAdapter\noptional AI]
H -->|adapter available| I[formatLogEntry]
H -->|no adapter| J[wrap as Markdown bullet]
I --> K[useInsertLogEntry → INSERT log_entries]
J --> K
K --> L[Query invalidation\n→ ChatArea refetch]
L --> M[Sidebar / dayStats refetch]
E --> N[useAddTodo\nis_important=0]
F --> O[useAddTodo\nis_important=1]
G --> P[useCompleteTodoByText]
N --> Q[INSERT todos]
O --> Q
P --> R[UPDATE todos]
Q --> S[Query invalidation]
R --> S
S --> M
src/
├── main.tsx ← initDB → migrations → render <Providers><App/>
├── app/
│ ├── App.tsx ← Root layout, header, modal + notice state, submit logic
│ ├── providers.tsx ← QueryClient + AppConfigProvider
│ └── AppConfigContext.tsx← chatDays, LLM adapter, current date (rollover)
├── components/
│ ├── ChatArea.tsx ← Central log feed (Markdown), inline edit/delete
│ ├── ChatInput.tsx ← Textarea, submit, command highlighting
│ ├── Markdown.tsx ← Shared react-markdown renderer (raw HTML disabled)
│ ├── ArchiveModal.tsx ← Year-view calendar archive + keyword search
│ ├── ArchiveConfirmModal.tsx ← Confirmation dialog for archive deletion
│ ├── LogModal.tsx ← Monthly / single-day log overlay
│ ├── SettingsModal.tsx ← LLM provider/model/chat_days config + app version
│ ├── NotesModal.tsx ← Undated scratchpad, view/edit + debounced autosave
│ ├── Sidebar.tsx ← Past days list
│ ├── TodoPanel.tsx ← Right-panel todo list
│ └── TodoItem.tsx ← Single todo row with inline editing
├── data/ ← Repositories: the only modules that import db.ts
│ ├── logEntriesRepo.ts
│ ├── todosRepo.ts
│ ├── settingsRepo.ts
│ ├── archiveRepo.ts
│ └── notesRepo.ts
├── hooks/ ← TanStack Query hooks (useLogEntries, useTodos, …)
├── markdown/
│ ├── htmlToMarkdown.ts ← Legacy HTML → Markdown converter
│ └── contentMigration.ts ← One-time startup HTML→Markdown migration
├── llm/
│ ├── adapter.ts ← LLMAdapter interface
│ ├── anthropic.ts ← Anthropic adapter
│ ├── factory.ts ← getAdapter() — reads settings, returns adapter
│ └── openai.ts ← OpenAI-compatible adapter
├── ai.ts ← formatLogEntry() — LLM formats raw text to Markdown
├── commands.ts ← parseCommand() — parses slash commands
├── db.ts ← query/execute/getSetting/setSetting wrappers
├── export.ts ← exportMarkdown()
├── feed.ts ← buildFeed() — pure chat-feed builder
├── todoLogic.ts ← todoStatus(), getTodoSections()
├── types.ts ← TodoItem, LogEntry, DayStats
├── utils.ts ← escapeHtml(), date helpers
└── styles.css
SQLite database is managed by tauri-plugin-sql. Migrations run automatically at startup from src-tauri/migrations/.
The connection string is the relative path sqlite:caplog.db (see src/db.ts and src-tauri/src/lib.rs). tauri-plugin-sql resolves relative paths into the app config directory, which is derived from the bundle identifier (com.bipin.caplog in src-tauri/tauri.conf.json). Dev and production builds share the same identifier, so they use the same file.
| Platform | Location |
|---|---|
| Windows | %APPDATA%\com.bipin.caplog\caplog.db (e.g. C:\Users\<you>\AppData\Roaming\com.bipin.caplog\caplog.db) |
| macOS | ~/Library/Application Support/com.bipin.caplog/caplog.db |
| Linux | ~/.config/com.bipin.caplog/caplog.db |
| Column | Type | Notes |
|---|---|---|
id |
INTEGER PK | |
date |
TEXT | YYYY-MM-DD |
raw_text |
TEXT | original user input |
formatted_text |
TEXT | AI-formatted HTML |
created_at |
TEXT | ISO 8601 |
| Column | Type | Notes |
|---|---|---|
id |
INTEGER PK | |
text |
TEXT | |
is_important |
INTEGER | 0 or 1 |
is_completed |
INTEGER | 0 or 1 |
deadline |
TEXT | nullable, YYYY-MM-DD |
created_at |
TEXT | ISO 8601 |
completed_at |
TEXT | nullable, ISO 8601 |
| Column | Type | Notes |
|---|---|---|
key |
TEXT PK | llm_provider, llm_api_key, llm_model, llm_base_url, chat_days |
value |
TEXT |
| Column | Type | Notes |
|---|---|---|
id |
INTEGER PK | single fixed row, always 1 |
content |
TEXT | raw Markdown/plain text scratchpad content |
updated_at |
TEXT | nullable, ISO 8601, set on save |
Known keys:
| Key | Default | Description |
|---|---|---|
llm_provider |
— | anthropic or openai |
llm_api_key |
— | API key for the selected provider |
llm_model |
— | Model name (e.g. claude-haiku-4-5-20251001) |
llm_base_url |
— | Base URL for OpenAI-compatible endpoints |
chat_days |
3 |
How many days of history to show in the sidebar and completed-todo cutoff |
Open Settings (gear icon) and configure:
| Field | Description |
|---|---|
| Provider | anthropic or openai |
| API Key | Your API key |
| Model | e.g. claude-haiku-4-5-20251001 or gpt-4o-mini |
| Base URL | OpenAI-compatible endpoint only (e.g. for local models) |
| Show days | Number of past days to show in the sidebar and completed-todo list (default: 3) |
LLM is optional — if not configured, entries are saved as plain text wrapped in <ul><li>.
The Settings modal footer also shows the running app version (e.g. v1.4.0), read at runtime via Tauri's getVersion() API. The version itself is sourced from src-tauri/Cargo.toml (package.version) at build time — tauri.conf.json has no separate version field to avoid drift.
# Install dependencies
pnpm install
# Run the full Tauri desktop app (Vite dev server + Rust backend)
pnpm tauri dev
# Frontend only (Vite on http://localhost:1420)
pnpm dev
# Type-check + build frontend
pnpm build
# Run tests
pnpm test
# Build distributable app
pnpm tauri build# Install Xcode Command Line Tools (if not already)
xcode-select --install
pnpm install
pnpm tauri buildOutput:
.dmginstaller →src-tauri/target/release/bundle/dmg/.appbundle →src-tauri/target/release/bundle/macos/
The app is unsigned. To open locally, right-click → Open instead of double-clicking (Gatekeeper will block a double-click on unsigned apps).
Run on a Windows machine or VM — Tauri does not support macOS → Windows cross-compilation.
# Install Rust
winget install Rustlang.Rustup
# Install Node.js (if needed)
winget install OpenJS.NodeJS
# Install pnpm
npm install -g pnpm
# Microsoft C++ Build Tools — required by Rust
# Download from https://visualstudio.microsoft.com/visual-cpp-build-tools/
# Select the "Desktop development with C++" workload
pnpm install
pnpm tauri buildOr use the helper script that checks prerequisites and loads the MSVC environment automatically:
# From the repo root
./scripts/build-windows.ps1Output:
.exeNSIS installer →src-tauri\target\release\bundle\nsis\.msiinstaller →src-tauri\target\release\bundle\msi\
First build takes 5–10 min while Rust compiles dependencies; subsequent builds are much faster. Installers are unsigned — Windows SmartScreen will warn users until a code-signing certificate is configured.
Q: Found version mismatched Tauri packages — e.g. tauri (v2.11.2) : @tauri-apps/api (v2.10.1)
The Rust tauri crate and the npm @tauri-apps/api / @tauri-apps/cli packages must share the same major.minor version. Update the npm side to match:
pnpm update @tauri-apps/api @tauri-apps/cliIf pnpm refuses to bump across a minor, pin the exact version in package.json (e.g. "@tauri-apps/api": "^2.11.0") and re-run pnpm install.
Q: LINK : fatal error LNK1104: cannot open file 'msvcrt.lib' (or libcmt.lib, kernel32.lib, ucrt.lib)
The Rust MSVC linker can't find the Windows SDK / CRT libraries because the MSVC environment variables (LIB, INCLUDE, PATH) aren't set in your shell. Two common causes:
-
You're running in a plain PowerShell window. Fix: launch "x64 Native Tools Command Prompt for VS 2022" from the Start menu, or load the env into your current shell:
cmd /c '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" && set' | Where-Object { $_ -match '^(LIB|INCLUDE|LIBPATH|Path)=' } | ForEach-Object { $n,$v = $_ -split '=',2; [Environment]::SetEnvironmentVariable($n,$v,'Process') }
(Adjust the path for
Community/Professionaleditions.) -
You have multiple VS installs and the one picked up is incomplete — e.g. only the
OneCoresubset of MSVC libs was installed, somsvcrt.liblives underVC\Tools\MSVC\<ver>\lib\onecore\x64\but not underlib\x64\. Fix: open the Visual Studio Installer, Modify the install, and add the "Desktop development with C++" workload (which installs the full Desktop x64 CRT). Or uninstall the partial toolchain so the linker uses a complete one. The helper scriptscripts/build-windows.ps1automatically skips installs that don't contain the Desktop x64 CRT.
Q: error: linker 'link.exe' not found
You have no MSVC toolchain at all. Install the "Desktop development with C++" workload via the Visual Studio Build Tools installer, then restart your terminal so link.exe is on PATH.
Q: WebView2 / WiX / NSIS download errors during bundling
tauri build downloads WiX (for .msi) and NSIS (for .exe) on first use. If you're behind a proxy, set HTTPS_PROXY before building. If a download is corrupt, delete %LOCALAPPDATA%\tauri and rebuild.
Q: First build is extremely slow
Normal — Rust compiles the full dependency tree (300+ crates) on first build. Subsequent builds reuse target\ and complete in seconds. Don't delete src-tauri\target\ unless you actually need a clean rebuild.
The tauri-action GitHub Action builds for macOS, Windows, and Linux without needing local VMs. Add .github/workflows/release.yml using that action to automate releases.
sample/caplog-mock.html is the canonical UI reference — a self-contained HTML file with dark theme, three-column layout, and working interactions. Match it for visual design when building new features.
Fonts: Instrument Serif (headings) + DM Mono (body). Dark theme via CSS custom properties (--bg, --surface, --text, etc.).
Licensed under the PolyForm Shield License 1.0.0 — free to use, modify, and distribute for any purpose except providing a product or service that competes with this software.
Required Notice: Copyright Bipin Radhakrishnan (https://github.com/rbipin/caplog)

