TomasPalsson/worklog/tree/main/mods/worklog
關於這個 mod
worklog
給討厭計時器的開發者使用的個人工時追蹤器。它會從 Claude Code、GitHub、Google Calendar 與 Jira 拉取活動,將活動聚成區塊,放進單一的本機 SQLite 檔案;再使用 claude -p 為每個區塊挑選工單並撰寫描述,等你在本機網頁介面審查後,把結果同步到 Tempo Cloud。
一切都在你的電腦上執行。除非你推送 Tempo 同步,否則沒有任何內容會離開;而在那之前,你會審查每個區塊。
安裝
curl -fsSL https://raw.githubusercontent.com/TomasPalsson/worklog/main/install.sh | bash
腳本會從 GitHub Releases 下載適合你平台的簽署發行版二進位檔(macOS arm64 或 linux x86_64),驗證後放到 ~/.local/bin/worklog。接著:
worklog setup # 一次性導入:資料庫 + 密鑰 + Claude hook
worklog day # 每日結束:收集 → 推斷 → 估算 → 審查介面
升級只需要一個命令,而且一律會驗證簽章:
worklog upgrade # 透過發行流程進行簽署自我更新
要從舊的
uv tool install遷移?請參閱docs/MIGRATION.md——只要一步。
架構
┌──────────────────────────── 你的 Mac ─────────────────────────────┐
│ │
│ ~/.local/share/worklog/worklog.db (單一事實來源, │
│ WAL 模式——並行寫入時 │
│ 讀取者可安全唯讀) │
│ ▲ ▲ │
│ │ │ │
│ 寫入(unix socket │ 直接讀取 │
│ 或 TCP 127.0.0.1:9323) │ 透過 bun:sqlite │
│ │ │ │
│ ┌────────┴────────┐ ┌───┴───────────────────┐ │
│ │ worklog(Rust) │ │ Docker:worklog-web │ │
│ │ · CLI │ │ · Bun + Next.js 15 │ │
│ │ · 收集器 │ │ · Server Components │ │
│ │ · 估算器 │───────▶│ · Server Actions → │ │
│ │ · axum daemon │ TCP │ host.docker │ │
│ │ · web 編排器 │ │ .internal:9323 │ │
│ └────────┬────────┘ └───────────────────────┘ │
│ │ 產生/管理 │
│ ▼ │
└─────────────────────────────────────────────────────────────────────┘
AI 估算器會把事件分類到 Jira 工單;沒有配對的事件會在網頁介面顯示為「unassigned」,再由人工重新指派。網頁容器直接讀取 SQLite(WAL 模式可安全進行並行讀取),寫入則透過 Next.js Server Actions → Rust daemon 的 TCP 連線(Docker Desktop 無法透過 macOS 虛擬機器代理即時 unix socket,因此容器與主機之間使用 TCP)。
只有 Rust daemon 會寫入資料庫——Server Actions 只是轉送變更並呼叫 revalidatePath 的薄層。
快速開始
worklog setup # 預檢 + 互動式密鑰 + 資料庫遷移
worklog hook install # 註冊 Claude Code hook
worklog day # 完整每日流程(收集 → 推斷 → 估算 → 介面)
要在不執行介面的情況下拉取所有內容:
worklog day --no-serve
命令
| 命令 | 用途 |
|---|---|
| worklog version | 印出內嵌版本 |
| worklog setup | 預檢 + 擷取密鑰 + 資料庫遷移 |
| worklog doctor | 環境、資料庫、密鑰的健全狀況報告 |
| worklog day [--day] [--no-serve] [--model] | 完整每日流程:收集 → 推斷 → 估算 → 網頁介面 |
| worklog collect [all\|jira\|github\|gcal] [--days] | 拉取遠端活動 |
| worklog infer [--day] | 以間隔逾時將事件聚成區塊 |
| worklog estimate [--day] [--model] | claude -p 填入 jira + 描述 + 分鐘數 |
| worklog sync [--day] [--dry-run] | 將已審查的區塊 POST 到 Tempo Cloud |
| worklog web up [--port] | 啟動 docker 化的 Next.js 介面 |
| worklog web down / status / logs / build | 容器生命週期 |
| worklog daemon [--socket] [--tcp] | Axum API 伺服器(unix + TCP) |
| worklog hook [install\|uninstall\|status] | Claude Code hook 接線 |
| worklog schedule [install\|uninstall\|status] | 排程收集(launchd / systemd --user) |
| worklog secret [set\|get\|rm\|list] | 將憑證存入作業系統鑰匙圈 |
| worklog db [migrate\|info\|path] | 資料庫操作 |
| worklog upgrade | 簽署自我更新 |
| worklog self-update [--check\|--dry-run\|--force] | upgrade 的低階別名 |
| worklog dev [keygen\|sign\|make-patch\|apply-patch] | 維護者工具 |
每個子命令都接受 --json 以輸出結構化結果。
儲存
- 資料庫:
~/.local/share/worklog/worklog.db(SQLite、WAL 模式)。 - 設定:
~/.config/worklog/(.env、google_credentials.json、google_token.json)。 - 密鑰: 作業系統鑰匙圈中服務名稱為
worklog的項目(macOS Keychain、Linux secret-service、Windows Credential Manager)。.env檔案仍然可用——透過worklog secret set …設定密鑰或重新執行worklog setup時,密鑰會延後遷移。 - 二進位檔與發行版:
~/.local/share/worklog/{bin,releases}/。
使用 $WORKLOG_HOME=<dir> 覆寫全部內容——把資料庫、socket、設定、bin、日誌與發行版集中到同一個根目錄。主要給測試與進階使用者使用。
切換估算器提供者
估算器有兩個可互換的後端:
claude_subprocess(預設)——呼叫claude -p。不需要設定,但PATH中必須有 Claude Code CLI。litellm——向任何相容 OpenAI 的代理發送 POST。LiteLLM 是參考實作。不用修改 worklog,就能把請求路由到 Anthropic、OpenAI、本機 Ollama、Bedrock 等服務。
透過 worklog setup(互動式)選擇,或設定環境變數:
export WORKLOG_ESTIMATOR_PROVIDER=litellm
worklog secret set litellm_base_url http://localhost:4000
worklog secret set litellm_api_key <your-proxy-key> # 未驗證的本機代理可留空
worklog secret set litellm_model anthropic/claude-haiku-4-5
worklog doctor 會回報目前的提供者與可達性探測。取消設定 WORKLOG_ESTIMATOR_PROVIDER(並執行 worklog secret rm worklog_estimator_provider)即可退回子程序路徑。
開發
cargo test --manifest-path rust/Cargo.toml
cargo clippy --manifest-path rust/Cargo.toml --all-targets --all-features -- -D warnings
cargo fmt --manifest-path rust/Cargo.toml --all
cd web && bun test && bun run typecheck && bun run build
本機發行版冒煙測試(無網路、不推送標籤):
bash scripts/release-smoke.sh
bash tests/install/smoke.sh
CI: .github/workflows/rust.yml 會在每次 push / PR 於 Linux 與 macOS 執行 fmt + clippy + 測試;.github/workflows/release.yml 會在每個 v* 標籤上建置、簽署並發布。
值得注意的檔案
rust/crates/worklog-core/——資料層:路徑、資料庫、儲存庫、密鑰、收集器、推斷、估算器、簽署更新器rust/crates/worklog-cli/——worklog二進位檔:CLI + 設定精靈rust/crates/worklog-core/sql/schema.sql——標準 SQL schemaweb/——Next.js + Bun 審查介面(docker 化)install.sh——透過 curl 管線執行的安裝器scripts/release-smoke.sh——發行流程的主機端 dry-run
安裝
請先查看作者 README,確認 marketplace 與外掛名稱;指令可能隨儲存庫結構而變動。
claude plugin marketplace add TomasPalsson/worklog claude plugin install worklog
原文 / README
worklog
Personal time-tracker for the developer who hates timers. Pulls
activity from Claude Code, GitHub, Google Calendar, and Jira into one
local SQLite file, clusters it into blocks, uses claude -p to pick a
ticket and write a description for each block, and syncs the result to
Tempo Cloud after you review it in a local web UI.
Everything runs on your machine. Nothing leaves until you push a Tempo sync — and you review every block before that happens.
Install
curl -fsSL https://raw.githubusercontent.com/TomasPalsson/worklog/main/install.sh | bash
The script downloads a signed release binary for your platform
(macOS arm64 or linux x86_64) from GitHub Releases, verifies it, and
drops it at ~/.local/bin/worklog. After that:
worklog setup # one-shot onboarding: db + secrets + Claude hook
worklog day # end-of-day: collect → infer → estimate → review UI
Upgrading is a single command and always verifies the signature:
worklog upgrade # signed self-update via the release pipeline
Migrating from the old
uv tool install? Seedocs/MIGRATION.md— one step.
Architecture
┌──────────────────────────── your Mac ─────────────────────────────┐
│ │
│ ~/.local/share/worklog/worklog.db (single source of truth, │
│ WAL mode — safe RO readers │
│ during concurrent writes) │
│ ▲ ▲ │
│ │ │ │
│ writes (unix socket │ reads direct │
│ OR TCP 127.0.0.1:9323) │ via bun:sqlite │
│ │ │ │
│ ┌────────┴────────┐ ┌───┴───────────────────┐ │
│ │ worklog (Rust) │ │ Docker: worklog-web │ │
│ │ · CLI │ │ · Bun + Next.js 15 │ │
│ │ · Collectors │ │ · Server Components │ │
│ │ · Estimator │───────▶│ · Server Actions → │ │
│ │ · axum daemon │ TCP │ host.docker │ │
│ │ · web orch. │ │ .internal:9323 │ │
│ └────────┬────────┘ └───────────────────────┘ │
│ │ spawns/manages │
│ ▼ │
└─────────────────────────────────────────────────────────────────────┘
Events are classified to a Jira ticket by the AI estimator; unmatched ones appear as "unassigned" in the web UI and are reassigned by hand. The web container reads SQLite directly (WAL mode = concurrent reads are safe), and writes flow through Next.js Server Actions → the Rust daemon over TCP (Docker Desktop can't proxy live unix sockets through its macOS VM, hence TCP between the container and host).
Only the Rust daemon writes to the DB — Server Actions are a thin
shim that forwards the mutation and calls revalidatePath.
Quickstart
worklog setup # preflight + interactive secrets + db migrate
worklog hook install # register the Claude Code hook
worklog day # full daily pipeline (collect → infer → estimate → UI)
To pull everything without running the UI:
worklog day --no-serve
Commands
| Command | Purpose |
|---|---|
| worklog version | Print the embedded version |
| worklog setup | Preflight + secrets capture + db migrate |
| worklog doctor | Environment, DB, secrets sanity report |
| worklog day [--day] [--no-serve] [--model] | Full daily pipeline: collect → infer → estimate → web UI |
| worklog collect [all\|jira\|github\|gcal] [--days] | Pull remote activity |
| worklog infer [--day] | Gap-timeout clustering of events into blocks |
| worklog estimate [--day] [--model] | claude -p fills jira + description + minutes |
| worklog sync [--day] [--dry-run] | POST reviewed blocks to Tempo Cloud |
| worklog web up [--port] | Bring up the dockerised Next.js UI |
| worklog web down / status / logs / build | Container lifecycle |
| worklog daemon [--socket] [--tcp] | Axum API server (unix + TCP) |
| worklog hook [install\|uninstall\|status] | Claude Code hook wiring |
| worklog schedule [install\|uninstall\|status] | Scheduled collection (launchd / systemd --user) |
| worklog secret [set\|get\|rm\|list] | Credentials in the OS keychain |
| worklog db [migrate\|info\|path] | DB operations |
| worklog upgrade | Signed self-update |
| worklog self-update [--check\|--dry-run\|--force] | Lower-level alias for upgrade |
| worklog dev [keygen\|sign\|make-patch\|apply-patch] | Maintainer tooling |
Every subcommand accepts --json for structured output.
Storage
- DB:
~/.local/share/worklog/worklog.db(SQLite, WAL mode). - Config:
~/.config/worklog/(.env,google_credentials.json,google_token.json). - Secrets: OS keychain under service name
worklog(macOS Keychain, Linux secret-service, Windows Credential Manager). The.envfile still works — secrets migrate lazily as you set them viaworklog secret set …or re-runworklog setup. - Binaries + releases:
~/.local/share/worklog/{bin,releases}/.
Override everything with $WORKLOG_HOME=<dir> — collapses db, socket,
config, bin, logs, releases into one root. Primarily for tests and
power users.
Switching estimator provider
The estimator has two interchangeable backends:
claude_subprocess(default) — shells out toclaude -p. Zero configuration. Requires the Claude Code CLI onPATH.litellm— POSTs to any OpenAI-compatible proxy (LiteLLM is the reference implementation). Lets you route to Anthropic, OpenAI, local Ollama, Bedrock, etc. without changing worklog.
Select via worklog setup (interactive) or set the env var:
export WORKLOG_ESTIMATOR_PROVIDER=litellm
worklog secret set litellm_base_url http://localhost:4000
worklog secret set litellm_api_key <your-proxy-key> # empty OK for unauthed local
worklog secret set litellm_model anthropic/claude-haiku-4-5
worklog doctor reports the active provider and a reachability probe.
Unset WORKLOG_ESTIMATOR_PROVIDER (and run worklog secret rm worklog_estimator_provider) to fall back to the subprocess path.
Dev
cargo test --manifest-path rust/Cargo.toml
cargo clippy --manifest-path rust/Cargo.toml --all-targets --all-features -- -D warnings
cargo fmt --manifest-path rust/Cargo.toml --all
cd web && bun test && bun run typecheck && bun run build
Local release smoke (no network, no tag push):
bash scripts/release-smoke.sh
bash tests/install/smoke.sh
CI: .github/workflows/rust.yml runs
fmt + clippy + tests on Linux and macOS on every push / PR;
.github/workflows/release.yml builds,
signs, and publishes on every v* tag.
Files of interest
rust/crates/worklog-core/— data layer: paths, db, repo, secrets, collectors, infer, estimator, signed updaterrust/crates/worklog-cli/— theworklogbinary: CLI + setup wizardrust/crates/worklog-core/sql/schema.sql— canonical SQL schemaweb/— the Next.js + Bun review UI (dockerised)install.sh— curl-piped installerscripts/release-smoke.sh— host-side dry-run of the release pipeline

