Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

worknow

A small local CLI that builds an automatically maintained view of active coding work across your machines.

It scans:

  • configured project directories (direct children only — fast & predictable)
  • per-repo: git branch, dirty state, last commit, recent commits within a window
  • running claude, codex, gemini, openclaw, xcodebuild, gradle, npm/pnpm/yarn, plus anything you add
  • optional openclaw sessions list / tasks list output when the binary is available
  • every prompt you typed into a Claude Code window, archived one file per day

Output is two sidecar files at ~/.openclaw/workspace/:

  • current-work.md — readable Markdown view, friendly for cross-machine browsing
  • current-work.json — structured payload consumed by the native macOS menu bar app in mac/

…plus a dated archive at ~/.openclaw/workspace/claude-context/ (see below).

Requires Python ≥ 3.11.

Install

git clone https://github.com/nvwalj/worknow.git
cd worknow
python3 -m pip install -e .

Then run:

worknow              # one-shot
worknow --watch 300  # refresh every 5 minutes (minimum 10s)
worknow --version

If editable install is inconvenient on a machine, the self-contained wrapper works without pip install:

./bin/worknow
ln -sf "$PWD/bin/worknow" ~/.local/bin/worknow

On macOS, install automatic refresh every 5 minutes via launchd:

./bin/install-launchd-macos

Uninstall it with:

./bin/uninstall-launchd-macos

If your checkout lives on an external disk, note that macOS forbids launchd background agents from reading non-boot volumes — even /bin/cp gets Operation not permitted, and there is no approval prompt because a background agent has no UI. Scheduling bin/worknow from /Volumes/... therefore fails silently on every interval while still looking installed. The installer detects this and stages a copy under ~/.local/libexec/worknow on the boot volume, then schedules that; re-run it after pulling to refresh the copy. It also verifies one real run and warns if the exit status is not 0.

Daily Claude context log

Claude Code already writes a full JSONL transcript per window, but it is unusable as a journal: one file per window, a long-lived window spans weeks, and roughly nine in ten events stored as user are tool results, skill injections, task notifications and slash-command expansions rather than anything a person typed.

worknow inverts that layout. It walks every window's transcript, keeps only genuine human turns, and writes one file per calendar day:

~/.openclaw/workspace/claude-context/
  2026-08-10.md      # readable: grouped by window, with times and replies
  2026-08-10.json    # same data, structured

Each day file records, per window, the window title, project path, git branch, the full prompt text, the first line of Claude's reply, the model that answered, and token totals — so "context" covers both what you said and how much was fed to the model to answer it.

worknow                        # refreshes the last 14 days alongside the report
worknow --context-only         # just the context log, skip the git/process scan
worknow --context-days 400     # one-time backfill of everything still on disk
worknow --no-context           # skip it

Day files are derived but durable: each run only rewrites days inside the window, so the archive keeps days whose transcripts have since been pruned from ~/.claude/projects. They are plain Markdown — readable in any editor, and in AI Memory Reader if you want a date-aware viewer.

Files are namespaced by machine (claude-context/<host>/2026-08-10.md). Transcripts are local to the machine that produced them, so two machines write different content for the same calendar day; namespacing means a synced archive merges instead of one machine clobbering the other.

Weekly review

worknow --week           # this week (Mon–Sun, ISO)
worknow --week last      # last week
worknow --week 2026-W32  # or any date inside the week: --week 2026-08-05

Writes ~/.openclaw/workspace/weekly/2026-W32.{md,json} — the source material for a weekly journal, joining the two halves that answer "what did I work on":

  • intent — your prompts that week, from the daily archive
  • outcome — commits in the same window, from git

Both halves are needed because they cover different projects. On a real week here, the top project by prompts had zero commits (research and learning work that never produces code) and the top project by commits had zero prompts (a scheduled agent committing twice a day, with nobody typing anything). Either half alone reports a different week than the one that happened.

The report leads with a per-project table — days active, prompts, commits, and which half saw it — then lists each project's prompts and commits in full. It is deliberately factual: no narrative, no scoring. Feed it to an agent to write the actual review.

Two things worth knowing about the numbers. Commits are filtered to the repo's own configured user.email, so a shared work repo contributes your commits and not your colleagues' — and per-repo identities are respected, which matters if you keep separate work and personal git identities. And prompts are filed under the directory Claude was running in, not the repo it changed, so driving one project from another project's window shows up on both sides of the table rather than as one tidy row.

Filtering rules, in order of strength: an event carrying toolUseResult is a tool result; isMeta / isCompactSummary / isSidechain mark injections, compaction summaries and subagent turns; origin.kind is set by current Claude Code on every real prompt and is authoritative when present; wrapper-prefix matching is the fallback for transcripts written before that field existed. Subagent transcripts (<session>/subagents/*.jsonl) are never read — those prompts were written by Claude, not by you.

Everything stays local. The archive contains your prompts verbatim, so treat the directory like the transcripts it is derived from.

Config

Config lives at ~/.config/worknow/config.toml. Run worknow --config-init to seed it with defaults.

Example:

output = "~/.openclaw/workspace/current-work.md"

project_roots = [
  "~/projects",
  "~/Project",
  "~/.openclaw/workspace",
]

process_keywords = [
  "claude", "codex", "gemini", "openclaw",
  "xcodebuild", "gradle", "npm", "pnpm", "yarn",
]

ignored_process_fragments = [
  "Google Chrome Helper",
  "chrome_crashpad_handler",
]

max_projects = 80
recent_commit_days = 7

context_log_enabled = true
context_log_dir = "~/.openclaw/workspace/claude-context"
context_log_days = 14          # how many days each run rewrites
context_log_max_chars = 4000   # per prompt; 0 = unlimited
context_log_include_replies = true
weekly_dir = "~/.openclaw/workspace/weekly"

If no config exists, worknow uses the defaults baked into cli.py.

Native macOS menu bar app

A small AppKit menu bar app lives in mac/. It reads the JSON sidecar the CLI writes and surfaces:

  • a menu bar badge with the active task count — a "task" is a tracked git repo that is dirty OR has a coding agent process running inside it
  • a draggable floating panel (left-click the menu bar icon to toggle) listing active repos and agent processes
  • auto-refresh every 30 seconds; panel position persists across launches

Right-click (or Control-click) the icon for the menu: show/hide the panel, Refresh now (r), and Quit worknow (q).

Build & run:

cd mac
./build.sh             # compiles a single-file Swift binary (no Xcode project)
./worknow-mac          # foreground — for a quick look; Ctrl-C ends it

./worknow-mac runs in the foreground and dies with the terminal. For daily use install it as a launchd agent (below) so it starts at login and survives closing the window.

Auto-start at login:

./install-launchd-macos
./uninstall-launchd-macos   # to remove

Quitting from the menu stops it for this session; the launchd agent starts it again at next login. To stop it for good, run ./uninstall-launchd-macos.

The app only displays data — it does not run the scanner itself. Schedule the Python CLI (bin/install-launchd-macos) so the JSON stays fresh, or the badge sits on a stale number forever without ever looking broken.

Git sync across machines

This repo is self-contained — push your fork wherever, clone on each dev machine, and run pip install -e .. Machine-specific paths stay in ~/.config/worknow/config.toml and never touch git.

The code travels; the data does not. Each machine reads its own ~/.claude/projects and writes its own day files, so a fresh clone reports that machine's week, not a merged one. To get a single weekly view across machines, sync the output directory itself — ~/.openclaw/workspace/ — with whatever you already use (a private git remote, iCloud, Syncthing). Day files are namespaced by host, so they merge rather than collide, and --week unions every host it finds in the archive. Commits are the exception: those already travel through your git remotes, so a pushed branch shows up in the weekly report from any machine that has the repo.

Development

python3 -m pip install -e '.[dev]'
pytest

License

MIT — see LICENSE.

About

Auto-maintained view of active coding work — agent sessions + dirty repos, CLI + macOS menu bar

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages