While Claude Code · Codex · Cursor write your code, Ocul-PM records every unit of work — shows you what actually changed as a local diff — and hands the pile back as standups, PR bodies and retrospectives. Local-first. No account, no server, no telemetry.
On Claude Code? Two lines in /plugin is another way in
Code has never been faster. Understanding has never been slower. Speed bought with memory — that is the trade of the agent era, and Ocul-PM is where it stops.
A record that writes itself as your agents work. A proof that shows every change where it happened. And a console with the agent itself inside it.
The moment an agent finishes, the entry is already written — what changed and why, which agent ran it on which model, classified as bug, feature, refactor, error or chore, in markdown a human reads.
The files an agent claims it touched — check them as a local diff, inside the app, before you commit. Put it side by side with the journal and compare what was said with what actually changed.
The real Claude Code runs inside the app. Every step — reading files, editing them, running commands — arrives as a card, and since v2.11 the edit itself is drawn as a diff.
Pick only what belongs to this project out of an export. Browsing the list is entirely offline and free.
Rules, skills and automations as one YAML file. A teammate's document shows what would change before it applies.
A fallback answer carries a badge, unreachable models are dimmed not hidden, and automations defer instead of failing.
Reloading the whole plan, journal and rules on every question is over. The list once, the bodies on demand.
"What did I do last week" gets history. "What should I name this" does not. No AI is called to decide.
A 2,500-character cut once swallowed "never write secrets". Now three lines stay resident and the rest arrives whole.
Five baked-in palettes used to be all of it. Now you build one and trade it as .json — the built-ins use the same format, so the built-ins are the examples.
There is no preview box. Change one color and the whole app changes with it. Colors you did not touch stay untouched.
Bind a theme to a project and only that window wears it. Five repos open at once stop blurring together.
It watches the folder, and when the edits go quiet it drafts what just happened. How long to wait is six tiers — 0.2s to 10min.
By hand · by agent · auto-draft · schedule · watcher · MCP — every entry carries its source. With one kind in the list, the filter row removes itself.
Actual firings over 7 days, and the rules that never caught once. A carefully written rule quietly doing nothing is invisible otherwise.
With four running, finding the one waiting on you meant clicking through windows. Now that session turns amber and "N waiting" takes you there.
Each command gets a status bar and failures are dotted down the right edge. ⌘↑/⌘↓ jump between them, and long output keeps its command pinned on top.
Click a block for "save as a journal entry" and "attach to the planner". Command, exit code, duration and the tail of the output arrive prefilled.
Move between screens, and find journals, plans, discussions and docs by title. Diff review and plan toggles are finished from the keyboard.
One window holds many projects as Chrome-style tabs. Tear one off into a window, drop it back to merge — the right-click menu does the same. Terminal sessions never drop.
Set "every Friday at 17:00, summarize this week" and the app runs it then. Even the reason it did not run is logged, and if the Mac was off it catches up exactly once.
You can start without the app — a hook bridge, 7 MCP tools and 5 skills install in two lines.
A session status icon and a popover briefing — you know a new entry landed without opening the app.
The UI is English or Korean, and the language the AI writes journals in is set separately.
Completions as you type, underlines where it is wrong. Hover types · go to definition · rename · code actions — standard LSP.
Rust · TypeScript · Python · Go. On your PATH it attaches, and when it is missing it says so — it does not fail quietly.
.oculpm/ · .github/ · .gitignore — the ones you open most often are visible.
Several files in tabs, two side by side in a split. Create, rename, drag to move; delete goes to the trash. Bring files in from Finder or with ⌘V.
Click the gutter for a breakpoint, then unfold the call stack and variables where it stopped. Rust · Python · Go.
Per item, "N times in 30 days" / "never fired", plus KB injected per session. Claude Code transcripts are counted on this machine — zero LLM, zero network.
Everything since the commit is overlaid in the editor, and you jump straight to the journal entry that changed this file.
Open from the tree, edit with syntax highlighting and save with ⌘S. 12 languages, and the theme follows the app.
If an agent edits the same file, saving asks with a banner instead of overwriting. Unsaved edits survive leaving the screen.
One button in a search result or the code map opens that file at that line, in the app.
No more leaving for Finder to look at a screenshot. Fit-to-window ↔ actual size on a checkerboard, PDFs as documents — up to 16MB.
Not the index — what is on disk right now. Case, whole word, regex, and replace one, one file or everything.
The Today activity ring reads as "N entries · N files · +N/−N lines". The tooltips that announced themselves on every hover went quiet.
This app is built with itself — every line below came out of Ocul-PM's own work journal.
/rules, /plan, /journal, /skill push things in deliberately). Records used often gain relevance; unused ones fade on a 30-day half-life. Settings gained a Context tab showing the standing instructions (global and per-project), the exact list this conversation received, the last recall budget and the candidates in relevance order with a per-item "forget"..json — the five built-ins use the same format, so "duplicate and edit" is a running start. There is no preview box: change one color and the whole app becomes that color, and colors you did not change are left alone (a theme that sets five background lines is a complete theme). A theme that specifies no accent keeps the accent you chose, and on macOS "follow the system accent" paints it with the OS color. Bind a theme to a project and only the window looking at that project wears it — five repos open at once stop blurring together. An imported file gets a fresh identifier, and a name collision asks (overwrite or keep a copy). A theme can only paint a fixed list of colors, so nothing else in the file reaches the screen..oculpm/, the AGENTS.md rules, the .gitignore change) and suggests committing it. Settings → Diagnostics gained a nine-line doctor (watcher · locks · adapters · API keys · index · shell integration · hooks · MCP) that fixes problems on the spot. A tab with a running command or an answering agent asks before it closes. In a project with no index, search and the code map say "no index + build one" instead of "no results", and ⌘/ shows every shortcut. The first-screen bundle went 538KB → 268KB, and a day's summary round trips dropped from 17 to 5 on Today and 30 to 4 on the journal.git init, node_modules was being indexed and a single line of a compressed file was duplicated hundreds of times, inflating the DB to 558MB — that is cleaned up (measured 382MB), and Settings → Diagnostics gained size and "compact". Closing a terminal now really ends vim, ssh and claude, and quitting the app leaves no orphaned adapters. A verification toggle on journal details plus related-entry chips close the review loop.All of it sits in one folder inside your project — as markdown a human can read.
Delete the app and the memory stays. Because it is yours.
A local-first AI project manager for developers who work with AI coding agents. It records what the agents did, organizes it, and lets you verify every change against a local diff before you commit it.
Claude Code, Codex CLI, Gemini CLI, Antigravity and pi work with no extra setup. Cursor, Windsurf, GitHub Copilot, aider, Cline and Zed work once you enable their rules file in Settings. Anything that reads AGENTS.md can be used with it, so you are never tied to one tool.
Yes. The Code screen browses the project tree, opens files and saves with ⌘S. Since v2.15.0 the editor understands the code — completion as you type, diagnostics underlined where they belong, hover types and docs, F12 / ⌘-click to jump to a definition, symbol rename that updates every file that uses it, and the code actions that come with a diagnostic. It works for Rust, TypeScript/JavaScript, Python and Go, and when a language server is missing from your machine it says so instead of failing quietly. It is not a VS Code fork — standard LSP is wired directly. Dotfiles (.oculpm/ · .github/ · .gitignore) show up in the tree. Search results and the code map jump straight to the line, and if an agent edits the same file, saving does not overwrite it — a banner asks which version to keep, and unsaved edits survive leaving the screen. Since v2.16.0 you get tabs and a split view, file create/rename/drag-move (delete goes to the trash), a breakpoint debugger (Rust · Python · Go) and an inline comparison that overlays what the agent changed. Since v2.19.0 ⇧⌘F adds project-wide search and replace against what is actually on disk. Since v2.20.0 images (png · jpg · gif · webp) and PDFs open in a preview instead of the editor — pictures on a checkerboard that reveals transparency, toggling fit-to-window ↔ actual size, PDFs as documents, up to 16MB regardless of the editor's 2MB limit (svg is both picture and code, so it still opens in the editor). Since v2.21.0 you can drag files and folders in from Finder or paste them with ⌘V — same names are never overwritten, they get a -2 suffix, folders recurse, and symlinks are skipped.
Yes. Since v2.10.1 ⌘J opens a terminal dock over whatever screen you are on. Dock it to the bottom (wide), the left or the right (tall) and drag the edge to size it. You can pull it out into a window of its own without dropping the shell — scrollback comes along. Since v2.22.0 sessions stand in a vertical list on the left where each card carries status, agent, elapsed time and last command — drag a session to the edge of the screen and the pane splits so you can watch two at once, and the split's handle (⠿) swaps them or pops one out as its own session. Font size is set in px in Settings → Appearance; line height and padding are a separate density setting (roomy / standard / compact).
That is exactly what v2.23.0 targets. When an agent calls for a human (terminal bell) that session turns amber and a "N waiting" banner appears above the list — click it and you land on the session that is waiting, then cycle to the next. A bell is certain because the program rang it; "quiet for 20 seconds" is a guess, and it is written as a guess. Output is also split per command: each command gets a status bar (green success, red failure), failure points are dotted along the right edge of the whole scrollback, and ⌘↑ / ⌘↓ jump between commands. Clicking a status bar offers copy, plus "save as a journal entry" and "attach to the planner" — the entry opens prefilled with the command line, exit code, duration and the last 40 lines of output. There is deliberately no re-run button; it only prefills the prompt, so nothing you have not looked at runs by itself.
Yes, since v2.24.0. Every item on the Skills & Rules screen carries an "N times in 30 days" or "never fired" badge, and the rules tab shows how many KB of conditional rules are injected per session. It is counted deterministically from the Claude Code transcripts on this machine — the moments a rule was actually injected and a skill was actually invoked — so no LLM and no network is involved. Rules without a paths filter load in full every session, so they are marked "every session" rather than counted, and "recount firings" starts over from scratch.
Exactly five things. ① LLM requests — sent straight to the provider you chose; we have no relay server. ② Update checks — one GitHub release file. ③ GitHub fetches for patch notes, bundles and theme files — only when you click. ④ A one-time embedding-model download the first time you enable semantic search: the model comes down, your code never goes up, and search is offline afterwards. ⑤ Notion, only if you opt in. Never leaves: journal entries (except what you ask the AI about), everything under .oculpm/, your source code (except snippets sent with a question), and API keys (OS keychain only). No usage statistics, no crash reporting — there is no analytics SDK in the app. The full list, and how to count the calls yourself, is on the privacy page.
Yes. Since v2.30.0, Settings → Data → "Import past conversations" opens an export (.json or .zip) from Claude and friends and lists what is inside with dates, titles, turn counts and a guessed entry type; you pick the ones that belong to this project and they become journal entries. Nothing leaves your machine while you read that list — skimming hundreds of conversations is entirely offline and free, and only what you pick calls the background model, once each. Entries land on their original dates, and re-opening the same file marks already-imported ones "imported" rather than billing you twice (they are not hidden — a conversation vanishing with no explanation is worse). Everything imported starts unverified: it did not happen in this repository, so it stays a draft until you read it and tick it off.
Everything local — journals, search, diffs, the planner — keeps working. Where models are involved, three things changed in v2.30.0. ① When your chosen model does not answer and a fallback replies instead, that reply carries a badge — previously a different model answered while the screen still showed the name you picked. The fallback applies to that one call; your settings are untouched. ② Unreachable providers are dimmed rather than hidden — hiding them reads as your settings having been wiped, and blocking them means you cannot pick one the moment connectivity returns (the reason is in the tooltip). ③ Automations defer instead of failing: a run that could not reach the network is recorded as "deferred" and does not burn its slot, so the catch-up rule picks it up once you are back. A failure that did get a reply (a 429, an auth error) means the network was fine — that is still a failure.
No. Since v2.29.0 it no longer reloads the whole plan, the recent journal and the working rules for every question. When a conversation starts it loads a list of what exists exactly once — and that list does not change by a single character until the conversation ends, because a stable prefix is what keeps the model-side prompt cache alive — and bodies are pulled only when needed. Past records attach only to questions carrying a recall signal: "what did I do last week", "what did I say", "how far did the plan get". The decision uses a Korean/English signal-word dictionary, so it calls no AI, and past the ~800 token ceiling it drops whole records starting with the least relevant. Rules used to be truncated at 2,500 characters, and that cut once swallowed the "never write secrets" clause outright — now only three lines stay resident and everything else arrives in full. To push something in deliberately: /rules · /plan · /journal · /skill. Settings → Context shows you exactly what goes in.
Yes. Since v2.28.0 a theme is a file. In Settings → Appearance you create one or "duplicate and edit" any of the five built-ins (Solarized · Sepia · Nord · Dracula · High Contrast), then export and import as .json — the built-ins use the same format, so the built-ins are the examples. There is no separate preview box because the app itself is the preview: change one color and the sidebar, cards, borders and status colors change with it. Colors you did not change are left alone — a theme that sets five background lines is a complete theme, everything else inherits the light or dark default, and each token has "reset to family default". A theme that specifies no accent keeps the accent you chose, and on macOS "follow the system accent" paints it with the OS color. Bind a theme to a project in the project editor and only the window looking at that project wears it. An imported file gets a fresh identifier, and a name collision asks whether to overwrite or keep a copy. A theme can only paint a fixed list of colors, so nothing else in the file reaches the screen.
Yes. Since v2.27.0 every record carries a provenance badge — by hand (a person writing in the app) · by agent (Claude Code and friends following the journaling rules) · auto-draft (a background model after the edits went quiet) · schedule · watcher · MCP · backfill (restored from git history). It shows on journal cards and details, in the Today activity feed and in the agent contribution rows of a retro, and a filter row above the journal narrows by source — not drawn at all when the list has only one kind, because a filter that cannot narrow anything is noise. No new field was invented: it is read deterministically from the session id and agent id already written in the entry file.
Yes. Since v2.26.0, set an instruction and a frequency in Settings → Automation and the app runs it at that hour — "every Friday at 17:00, summarize this week's commits and open items", for example. Frequencies cover once, every N minutes, every N hours, daily, weekly, monthly, yearly and cron, and the first visit suggests three examples (weekly dev summary, morning briefing, monthly retro) switched off — you create them with a click and decide about enabling afterwards. Definitions are markdown files under .oculpm/automation/, so you can edit them by hand and commit them with your team. Automation is entirely opt-in, and if no background model is chosen it is skipped silently rather than erroring — so nothing bills you without your knowing. There is a daily run cap (20 by default), and the run log records skips, drops and failures with reasons, not just successes. If the Mac was asleep or the app was closed, it catches up exactly once instead of stacking up. Since v2.27.0 the trigger can be the working folder rather than the clock: when file changes go quiet for the interval you set (0.2s to 10min), it drafts a journal entry or updates the plan.
Yes. Since v2.9.0 one window holds several projects as tabs. Drag to reorder, or out of the window to make a new one, and since v2.22.0 you can drop a tab onto another window's tab strip to merge them back (the insertion point is shown while you drag, and moving the last tab closes the empty window). Since v2.24.0 it behaves exactly like Chrome — the moment a tab leaves the strip it becomes a real window that follows your hand off-screen and over other apps, and aiming at another window's tab strip hides the one you are holding and shows where it will land. Since v2.25.0 a torn-off window can be dragged back: a window with a single tab is picked up whole and merges when dropped (Escape puts it back where it was). Right-click a tab for the same operations from a menu, or Shift+F10 from the keyboard. Each project remembers its own screen, filters and sidebar state, and terminal sessions belong to the project, so they survive a tab moving between windows. ⌘T new tab, ⌘W close tab, ⇧⌘N new window.
From the journal entries it generates standup text, PR bodies and weekly reports, plus retrospectives over a date range and .md export. With an AI configured it polishes the result; without one it still works with the default format.
Yes, in beta. Since v2.18.0 the Mac runs a server reachable only inside your Tailscale network, and a phone browser opens today's journal, the planner, discussions and the AI chat. Turn the server on in Settings → Mobile, scan the QR code and pair once with a six-digit code; add it to the home screen and it behaves like an app. The theme you picked on the desktop carries over (themes you built yourself follow only their light/dark family on the phone for now), and your AI API keys stay in the Mac keychain. During the beta, search, retros and the code screen are desktop-only.
No. Everything lives in your project's .oculpm/ folder and a local SQLite cache. Only three things leave: the LLM API calls you make yourself, the update check for new versions, and a GitHub fetch when you ask for a plugin bundle or release notes. The v2.18.0 mobile bridge (beta) is the same — it is served only inside your own Tailscale network, never exposed to the public internet, and the phone talks to your Mac without passing through a third-party server.
They survive. Since v2.19.0 terminal sessions are held by a process detached from the app, so after an auto-update or a restart your terminal tabs come back with their scrollback and whatever was running (including Claude Code sessions). Closing a terminal tab or a project tab yourself still cleans that session up as before.
Yes. In Claude Code, run /plugin marketplace add bunhine0452/Ocul-PM and then /plugin install oculpm@oculpm — two lines that set up the hook bridge, 7 MCP tools and 5 skills across all your projects. Journals and plans accumulate as markdown under .oculpm/, and if you install the app later it reads those records exactly as they are.
Yes. Since v2.8.5, Settings → Appearance lets you pick English or 한국어 and all 12 screens plus the error messages follow. The language the AI writes journals, retros and planner items in is set separately, so an English UI with Korean records (or the reverse) is possible, and documents already written are never rewritten.
Yes. The macOS (Apple Silicon) build is a free download from GitHub Releases. Intel and Windows builds are planned, and later versions update themselves from inside the app.
Yes. Because Ocul-PM is local-first, adopting it on a team does not move your code or your records anywhere. For enterprise rollouts, team adoption and partnership proposals, write to bunhine0452@gmail.com — the person who built it reads and answers.
No sign-up, no setup, no fee. You download it, and that is the whole thing.
Plenty of developers move fast. The ones who remember go far.