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 守护进程│ TCP │ host.docker │ │
│ │ · web 编排器 │ │ .internal:9323 │ │
│ └────────┬────────┘ └───────────────────────┘ │
│ │ 生成/管理 │
│ ▼ │
└─────────────────────────────────────────────────────────────────────┘
AI 估算器会将事件归类到 Jira 工单;未匹配的事件会在网页界面中显示为「unassigned」,再由人工重新分配。网页容器直接读取 SQLite(WAL 模式可安全并发读取),写入则经过 Next.js Server Actions → Rust 守护进程的 TCP 连接(Docker Desktop 无法通过 macOS 虚拟机代理实时 unix socket,所以容器与主机之间使用 TCP)。
只有 Rust 守护进程会写入数据库——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

