🇰🇷 한국어 README
- A native macOS calendar for personal daily planning and progress tracking.
- Single-user, local-first, intentionally small.
- Lives in the menu bar, responds to a global hotkey, and can optionally ask an LLM to write a daily review.
Obsidian is where my work lives — project notes, references, anything that has to outlast the current job. What it was never good at, for me, is the other half of the day: what am I actually doing today, what did I leave unfinished last week, when is that appointment. Dayflow is that half. I wrote it for myself, and I open it every morning.
- Three views — Day / Week / Month, all backed by one markdown body per day.
- Block-based WYSIWYG editor — powered by BlockNote, with live rendering of headings, bullets, and checklists.
- Rich text styling — bold, italic, underline, strikethrough, inline code, plus text and background color from a top toolbar. Full fidelity is stored alongside the markdown body so colors and underlines survive across reloads.
- Code blocks and dividers — typing
```on an empty line turns it into a code block, and---(or***) into a full-width divider, the moment the line reads that way — no Space or Enter. Both are in the slash menu too. Code blocks are monospaced, dark-themed, syntax-highlighted per language, with fenced markdown round-tripping. - Tables — pick "Table" from the slash menu and choose dimensions from a Notion-style grid picker (up to 6 × 6). Backspace on an empty cell removes the entire table.
- Monthly plan — a separate editor per month for the TODOs that belong to the month as a whole, not to any single day. Shown in the Month view right rail.
- Appointments — time-stamped items (meetings, reminders) stored in a dedicated
appointmentstable. All day when you know the date but not the time; add an end date for something that runs over several days. Surfaced in every view: the Day rail (multi-day ones show "day 2 of 3"), chips and continuous bars in Week columns, bars across Month cells plus a sorted "this month" list in the Month rail, which is the one place they're created and edited. Repeats: weekly (13 weeks) or monthly (12 months). Quick Throw (⌘⇧I) has a Task / Appointment tab so you can jot either one without leaving your current app. - Images — paste or drop a picture straight into a note. The bytes are copied into
~/Library/Application Support/Dayflow/attachments/and the note keeps only a reference, so images survive restarts without bloating the database. Copying an image out of a web page stores the picture itself rather than a link to someone else's server. - Global search (
⌘⇧F) — one palette over every day note, appointment, and month-plan section. Matching is substring-based, so a Korean query lands mid-word too.↑/↓to move,↵to jump to whichever view the hit lives on. - Task carry-over — whatever you left unchecked in the past week shows up as a banner on today. Review the list, keep what still matters, and those tasks move — sub-items included, under the same heading (
## Worketc.) they sat under — and are removed from the day they were written on, so nothing is counted twice. A blank today first gets the most recent day's headings. - On-hold status — right-click any checkbox for a To do / Done / On hold menu. On-hold ("보류") is a third state — a task you've deliberately parked — rendered in fluorescent blue (mark
- [~]). Held tasks are excluded from the carry-over banner and the completion ratio, so parking something stops it from nagging without marking it done. - AI Planner (wand icon in Day/Week) — dump a pile of tasks, pick a date range, and an LLM distributes them across the days. It only schedules what you typed (never drags in old unfinished tasks), asks a clarifying question or two when the answer would actually change the plan, and lets you refine the result with free-form feedback before anything touches your notes. Applied plans land as a
## 📋 Plansection per day; re-running replaces that section but keeps whatever you'd already checked off. A network hiccup mid-conversation surfaces as a retry banner, never a lost draft. See AI Planner below. - Appointment reminders — opt-in macOS notifications, 0 / 5 / 10 / 30 / 60 minutes before an appointment starts. Off until you turn them on.
- Google Calendar import — opt-in, read-only. Your events are mirrored into Dayflow's appointments and show up in every view; Dayflow never writes anything back to Google.
- Local-only by design — notes and reviews live in
~/Library/Application Support/Dayflow/, API keys live in macOS Keychain. Nothing leaves the machine unless you ask for it: the only two things that ever talk to a server are the LLM review (when you press Generate) and the Google Calendar import (if you connect it). - Copy and paste — lists from Notion, Google Docs, web pages, terminals and VS Code keep their nesting and checkboxes. Copying out gives indented markdown.
⌘⇧Vpastes text exactly as written. - Automatic backups — while Dayflow runs, a full snapshot is saved once a day to
~/Library/Application Support/Dayflow/backups/; the newest 14 are kept. Settings → Data shows it in Finder. - Optional LLM daily review — OpenAI or Anthropic, picked and configured entirely inside the app.
- Themes — Midnight, Graphite and Navy (dark), Paper and Sepia (light). Switch from the palette button in the top bar or in Settings; the editor, menus and window appearance all follow, and code blocks stay dark on light themes so their highlighting stays readable.
- Bilingual — English or Korean, switchable in Settings, no relaunch-from-terminal needed. The menu bar and the editor's slash and status menus follow too.
- Keyboard —
⌘1/⌘2/⌘3for Day / Week / Month,⌘←/⌘→previous / next,⌘Ttoday,⌘⇧Fglobal search,⌘⇧Vpaste as plain text.
- Markdown editor on the left. The right rail, top to bottom:
- This week as seven rings, each filled by that day's done ratio; click one to open that day.
- Today's progress: the done count, plus a progress bar per heading (
## …) of the note. Clicking a heading row scrolls the editor to it. - Appointments (multi-day ones included), tasks on hold from the last 30 days, and the AI review. Empty sections collapse to one line.
- Checklists, memos, and nested lists all live in one body per day.
- A banner appears at the top when earlier days still hold unchecked tasks — see Task carry-over.
- Top toolbar: B / I / U /
S/{ }, plus text colour and highlight. Select text, click a button. With nothing selected it fades back so the page reads as a page; a selection brings it back. The colour swatches stay folded behind their two buttons — the underline on each one shows the colour the selection already carries. - Slash menu (
/on an empty line): headings, lists, code blocks, tables, and more.
- Seven columns, one per weekday. Multi-day appointments run across the columns as continuous bars, then each day's appointment chips, then its tasks grouped by heading.
- Task titles wrap to two lines, with the full text on hover; a busy day's list scrolls inside its own column.
- Checkboxes are tappable in place — toggling a box does not navigate away from the week, and the day's colours and underlines are kept.
- Heatmap colored by how much you actually did each day. Each cell previews its open tasks and ends with a done/total bar; hovering lists every open task.
- Multi-day appointments run across the cells as bars, stacked into separate lanes when they overlap.
- Right rail, top to bottom: month metrics (completion rate, longest streak, busiest weekday), every appointment in the month, and a Month plan editor for month-scoped TODOs.
- Month view is where scheduling happens. The add form stays collapsed behind New — it's wider than the rail, and you schedule occasionally rather than constantly. It opens on the day you're looking at, with All day and + End date controls. The pencil on a row opens it pre-filled; × asks before deleting.
- One palette over day notes, appointments, and month-plan sections at once. The icon on each row tells you which is which.
- Substring matching, not word matching — searching
산finds부산. (This is why it usesLIKEand not SQLite's FTS5: theunicode61tokenizer treats a run of Korean as a single token, so mid-word queries would return nothing.) ↑/↓to move,↵to open. Opening a hit switches to the view that owns it — Day for a note, Week for an appointment, Month for a plan section — and lands on the right date.
- A banner appears on today whenever the past 7 days still hold unchecked tasks.
- The same task left open on several days collapses into one row, and anything already written on today is left out.
- Each row shows the heading it came from and how many sub-items travel with it.
- Confirming moves the tasks with their sub-items: placed under the same heading in today's note (added if missing), deleted from the source day, text colours included. If a source day changed while the sheet was open, that block is skipped rather than guessed at.
- Pick one from the palette button in the top bar, or Settings → General → Appearance. Below is the light Paper theme.
- One sheet, three steps: dump tasks + pick a range → (optional questions) → preview → Apply. Reachable from the wand icon in the Day and Week nav bars; Day prefills the selected day, Week prefills the visible week.
- Only the tasks you typed get scheduled. Existing appointments are passed in as constraints (blocked time), not as work to plan — and old unfinished tasks / month-plan goals are deliberately left out, so the plan is exactly what you asked for.
- The model asks clarifying questions only when the answer would change the plan (priorities, deadlines, effort). Answer them, or hit Skip — just plan it and it proceeds on reasonable assumptions (disclosed in the rationale). Capped at two rounds.
- The preview is editable by conversation: type free-form feedback ("move the blog post earlier", "leave Thursday empty") and Revise re-plans in the same thread, as many times as you like, before you commit.
- Apply writes a
## 📋 Plan (…)section into each day's note. Re-running the planner for a day replaces that section but preserves any items you'd already checked off. Nothing is written until you press Apply. - Turns are transactional: if the network drops mid-conversation, the sheet keeps your progress and shows a Retry banner instead of throwing the whole draft away.
+------------------------------------------------------------------+
| 1. Input |
+------------------------------------------------------------------+
| |
| Dump your tasks (one per line or free-form), |
| pick a date range. |
| |
| +----------------------------------------------+ |
| | set up K8s production server | |
| | publish first blog post (vLLM) | |
| | rewrite resume | |
| +----------------------------------------------+ |
| From [Wed Jul 15] To [Sun Jul 19] |
| [ Generate plan ] |
| |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| 2. Questions (only if it would change the plan) |
+------------------------------------------------------------------+
| |
| Which is more urgent: the server or the post? |
| ( Server first ) ( Post first ) |
| How long will the resume rewrite take? |
| [ ________________________________ ] |
| |
| [ Skip - just plan it ] [ Answer ] |
| |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| 3. Preview -> Apply |
+------------------------------------------------------------------+
| |
| Wed Jul 15 - [ ] K8s cost survey |
| Thu Jul 16 - [ ] set up K8s cluster |
| Fri Jul 17 - [ ] write vLLM blog post |
| Sat Jul 18 - [ ] rewrite resume |
| |
| Not quite right? Tell me what to change... |
| [ move the blog post earlier ] [ Revise ] |
| |
| [ Back ] [ Apply ] |
| |
+------------------------------------------------------------------+
- General — grouped into Appearance (language, theme, editor font sizes, public-holiday overlays for Korea / US / both — bundled with the app, no network), Alerts (appointment reminders and how far ahead they fire), and Data (the date you started using Dayflow, and automatic backups — the latest snapshot, shown in Finder).
- Calendar — connect a Google Calendar and pick which calendars to mirror. Read-only. See Google Calendar below.
- AI Review — provider (OpenAI or Anthropic), API key, model, and the system prompt that drives the daily review.
- macOS 14.0 or later.
- Head to the latest release.
- Download
Dayflow-<version>.zip. - Unzip — you get
Dayflow.app. - Drag
Dayflow.appinto/Applications. - First launch will show a "cannot verify developer" warning because the release is ad-hoc signed (no paid Apple Developer account yet). Two ways around it:
- Finder: right-click
Dayflow.app→ Open → confirm in the dialog. Once, then it's trusted forever. - Terminal:
xattr -cr /Applications/Dayflow.appthen double-click as usual.
- Finder: right-click
- Launch from Launchpad or Spotlight. That's it — no build step, no Xcode required.
Only needed if you want to modify the code or test an unreleased commit.
Extra requirement: Xcode Command Line Tools (xcode-select --install).
git clone https://github.com/tryumanshow/dayflow
cd dayflow/Dayflow-macOS
./build.sh- Builds the release binary.
- Assembles the
.appbundle with version and build number injected. - Renders the app icon from
tools/make_icon.py. - Ad-hoc signs and installs to
/Applications/Dayflow.app. - CI runs the exact same
build.shon amacos-14runner for every merge tomain, so the release zip and your local build produce bit-for-bit the same.app(modulo timestamps).
cd dayflow/Dayflow-macOS && swift build \
&& killall DayflowApp \
; cp .build/debug/DayflowApp /Applications/Dayflow.app/Contents/MacOS/DayflowApp \
&& open /Applications/Dayflow.appcp Dayflow-macOS/com.swryu.Dayflow.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.swryu.Dayflow.plist- Undo with
launchctl unload ~/Library/LaunchAgents/com.swryu.Dayflow.plist.
- Open Dayflow → Settings… (or press
⌘,). - Pick a Provider — OpenAI or Anthropic. Each provider has its own independent Keychain slot.
- Paste an API Key. The field is a
SecureField; if a key is already saved you'll see a hint and can leave the field blank while editing other fields. - Pick a Model from the provider's preset dropdown.
- Optionally rewrite the System Prompt. The built-in default asks for a three-section review (what went well / what got stuck / tomorrow's top 3). Hit Reset to default to go back.
- Click Test connection to fire a real request with the current settings. Any error (URL, status code, body snippet) is surfaced inline.
- Click Save.
Key issue pages:
- OpenAI: https://platform.openai.com/api-keys
- Anthropic: https://console.anthropic.com/settings/keys
- Settings → Language.
- Options: System default, English, 한국어.
- Requires a relaunch of Dayflow for the override to take effect.
- Launching the app drops you into today's Day view.
- Type directly in the editor — everything persists automatically (debounced).
- Switch views via the
Day/Week/Monthtabs at the top. - Step through dates with the chevron buttons; jump back to the current day with
Today.
| Shortcut | Action |
|---|---|
Cmd+N |
Open Quick Throw |
Cmd+Shift+I |
Global Quick Throw (works even when Dayflow is in the background) |
Cmd+Shift+F |
Search all notes, appointments, and month plans |
Cmd+F |
Find inside the current editor |
Cmd+← / Cmd+→ |
Previous / next — a day, a week, or a month, matching the view you're in |
Cmd+T |
Jump back to today |
Cmd+Option+S |
Show or hide the side rail |
Cmd+= / Cmd+- / Cmd+0 |
Editor zoom in / out / reset |
Cmd+R |
Refresh data |
Cmd+, |
Settings |
- [ ] open item
- [x] done item- Checkbox state is reflected immediately in the right-hand progress panel and the Week / Month view aggregates.
- In the Week view, tap a checkbox directly inside its column to toggle without navigating into the Day view.
- Settings → General → Enable reminders. macOS will ask for notification permission the first time.
- Pick how far ahead you want to be told: at start time, or 5 / 10 / 30 / 60 minutes before.
- Reminders are rescheduled from scratch whenever your appointments change, so edits and deletions take effect immediately.
- macOS only keeps a bounded number of pending local notifications, so Dayflow schedules the soonest 60 upcoming appointments and refills as they fire.
- All-day events get no reminder — their midnight start is a storage detail, not a time anything actually happens.
Import only. Dayflow reads your calendar and never writes to it — imported events can't be edited or deleted inside the app, because the next sync would put them straight back.
You bring your own OAuth client. Dayflow ships no Google credentials: an OAuth client id can't be kept secret inside an open-source binary (anyone can pull it out with strings), and the API quota and consent screen belong to whoever owns the client. So it's the same shape as the LLM API key — your credentials, your Keychain.
- In Google Cloud Console, create a project.
- APIs & Services → enable the Google Calendar API.
- Credentials → Create credentials → OAuth client ID → application type Desktop app.
- Copy the Client ID and Client secret into Dayflow: Settings → Calendar.
- Click Connect Google Calendar. Your browser opens Google's consent screen; approve it and the tab tells you to come back.
No web server, no domain, and no nginx are involved. Google's installed-app flow lets a desktop client redirect to http://127.0.0.1 on any port, so Dayflow opens a socket for the few seconds the consent screen is up, reads the authorization code off the single request the browser makes to it, and closes. The exchange is protected with PKCE, and the refresh token goes into the macOS Keychain.
After connecting:
- Tick which calendars to mirror. Nothing ticked means your primary calendar only.
- Dayflow syncs on launch, every 30 minutes, and whenever you press Sync now.
- The window it mirrors is 30 days back to 180 days ahead.
- Mirrored rows are marked with a small ⓖ and carry no edit or delete buttons.
- Disconnect forgets the grant and removes every mirrored event. Appointments you typed yourself are untouched.
- Requested scope:
calendar.readonly— Google will not grant Dayflow write access even if something asked for it.
- Database —
~/Library/Application Support/Dayflow/dayflow.db(SQLite, WAL mode). Tables:day_notes,reviews,appointments, andmonth_plan_sections(plus its edit history). Everything a day note contains rides inside the markdown body. - API keys and the Google refresh token — macOS Keychain. Never written to plain files, environment variables, or logs.
- Provider / model / custom system prompt / language override / reminder preferences / Google client id —
UserDefaults(also local-only). - Outbound traffic — exactly two things reach the network, and only if you turn them on:
- LLM review, when you press Generate. One HTTPS request per press, to the provider you picked. Body contains: the date string (
yyyy-MM-dd), that day's raw markdown, and the current system prompt. - Google Calendar, if you connect it. Dayflow reads your events over
calendar.readonly. Your notes are never part of that request — it's a download, not an upload.
- LLM review, when you press Generate. One HTTPS request per press, to the provider you picked. Body contains: the date string (
- No other day's data, no device identifier, no telemetry, no crash reports — ever.
- Backup — copy
~/Library/Application Support/Dayflow/somewhere safe. The DB plus its WAL and SHM files are all that matter.
- Development and contribution info: CONTRIBUTING.md.






