npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@midaspenn/timelog

v1.0.0

Published

个人时间账本系统

Readme

timelog — 个人时间账本系统 (PDL)

一、项目简介

timelog 是一个本地命令行时间记录工具,用于追踪"你现在主要在做什么",并在一天结束时生成可读的时间分布报表。

主要用途:为 AI 提供时间上下文数据。 通过让 AI 助手调用 timelog 的命令,AI 可以随时查询你当前在做什么、今天的时间分布如何、哪些时间段未被记录——从而给出更贴合你实际状态的建议和回应。人工使用同样完全支持。

它不是什么:

  • 不是番茄钟,不要求你每隔几分钟就点一次
  • 不是全量流水账,不追踪每一秒的去向
  • 不是任务管理器,不关心 TODO / Done 的状态

它是什么:

  • 稀疏的重要状态记录器:只在状态切换时记录
  • 分层时间区间模型:主状态(一心一意)+ 上下文(并行背景)分开记录
  • 事后补记友好:支持用 --at 指定历史时间点,或用 primary add 补录整段历史区间
  • 报表驱动反馈:每天/每周自动推导覆盖率、间隙、专注分布
  • AI 友好接口:输出为纯文本 + 非零退出码,非 TTY 环境自动关闭颜色,方便 AI 工具直接调用和解析

二、核心对象模型

Primary Block(主状态)

你在某段时间"主要在做的事"。任意时刻最多只有一个进行中的主状态,两条记录的时间区间绝对不能重叠。

每条主状态有:

  • 名称(如"写架构文档")
  • 分类工作 / 学习 / 休息 / 生活维护 / 杂事
  • 任务属性目标任务 / 支撑任务 / 固定开销 / 休息恢复 / 漂移/分心
  • 备注(可选)
  • 开始/结束时间(UTC ISO-8601,结束为空表示进行中)

Context Block(上下文状态)

与主状态并行存在的背景状态,如"听音乐""在通勤"。允许多个并发,互相之间可以重叠。

每条上下文有:

  • 名称
  • 类型思考 / 移动 / 音频 / 背景事务

Routine Template(弹性开销模板)

静态配置规则,描述"某项固定活动每天应该花多少时间"。报表生成时用于对比实际时长并给出偏差反馈。

Derived Gap(推导间隙)

查询时实时推导,永不持久化。从查询窗口中减去所有主状态后剩余的空白区间,代表"未被记录的时间"。


三、安装与运行

依赖要求: Node.js 18+(推荐 22),npm

# 克隆/进入项目目录后:
npm install        # 安装依赖,同时自动触发 prepare 脚本完成 TypeScript 构建

npm install 会自动运行 npm run build(通过 prepare 钩子),首次安装后即可使用。

运行方式

项目有三种执行方式,适用场景不同:

1. 开发模式 — 改了源码立即生效,无需手动构建

npm run dev -- <命令> [参数]
npm run dev -- primary start "写代码" "工作" "目标任务"

2. 本地构建后运行 — 开发验收推荐,本文档所有示例均使用此形式

node cli.js <命令> [参数]
node cli.js primary start "写代码" "工作" "目标任务"

cli.js 是项目根目录的入口 shim,始终转发到 dist/cli.js这是最稳妥、最不依赖环境的本地调用方式——只要在项目目录下执行,不需要任何额外的 PATH 配置。文档里统一写 node cli.js 就是这个原因。

3. 安装到 PATH 后使用 timelog 命令

package.json 中声明了 "bin": { "timelog": "./cli.js" },这只是注册了可执行入口的名称,并不意味着当前 shell 里直接输入 timelog 就能生效。需要先显式安装:

# 开发期:在当前 Node 全局 bin 目录创建符号链接
npm link

# 或永久全局安装
npm install -g .

安装后可在任意目录使用:

timelog primary start "写代码" "工作" "目标任务"

如果未做上述安装,在项目目录里直接输入 timelog 会报"命令未找到",用 node cli.js 即可。

4. npx timelog — 不想全局安装、又想省略 node cli.js 前缀时的折中

在项目目录下,npm/npx 能解析到当前包自身的 bin 入口,因此无需 npm link 也可以用:

npx timelog primary start "写代码" "工作" "目标任务"

适合偶尔使用或快速验证,不需要修改全局环境。对日常开发和验收,node cli.js 仍然更直接;若在项目目录之外运行且 timelog 不在 PATH 里,npx 会转而从 npm registry 拉取(可能与本地版本不符),此时应改用 node cli.js 或先执行 npm link

shim 行为:dist/ 不存在(未构建),cli.js 会打印明确提示而不是报神秘错误:

错误: dist/cli.js 不存在,请先构建项目:
  npm run build

或直接以开发模式运行(无需构建):
  npm run dev -- <命令>

四、数据存储位置

所有数据保存在本地 SQLite 文件。

默认按平台使用各自的应用数据目录:

  • Linux$XDG_DATA_HOME/timelog/timelog.sqlite
    • 若未设置 XDG_DATA_HOME,回落到 ~/.local/share/timelog/timelog.sqlite
  • macOS~/Library/Application Support/timelog/timelog.sqlite
  • Windows%LOCALAPPDATA%\timelog\timelog.sqlite
    • 若未设置 LOCALAPPDATA,回落到 %USERPROFILE%\AppData\Local\timelog\timelog.sqlite

也可以通过环境变量覆盖默认位置:

TIMELOG_DB=/your/path/timelog.sqlite node cli.js primary current

这是纯本地持久化,不涉及任何云同步或网络请求。Linux 下重置数据库示例:

rm -f ~/.local/share/timelog/timelog.sqlite
# 下次运行时自动重建表结构

五、命令总览

下面的树形图用 timelog 表示命令入口,实际执行时请按你的环境替换为 node cli.js(本地开发)、timelog(已安装到 PATH)或 npx timelog(项目目录内免安装调用)。

timelog
├── primary       管理主状态(互斥,最多一个进行中)
│   ├── start     开始新主状态(如有进行中则先关闭)
│   ├── switch    切换到新主状态(同 start,语义更清晰)
│   ├── stop      结束当前进行中的主状态
│   ├── current   查看当前状态
│   ├── add       补记历史区间
│   └── list      列出最近 20 条记录
│
├── context       管理上下文状态(可并发,互不干扰)
│   ├── start     开启新的上下文
│   ├── stop      结束上下文(按 ID 或 --name --latest)
│   └── list      列出上下文记录
│
├── routine       管理弹性开销模板(报表反馈用)
│   ├── add       新增模板
│   ├── list      列出所有模板
│   ├── enable    启用模板
│   ├── disable   停用模板
│   └── update    更新模板参数
│
└── report        生成报表
    ├── day       日报表
    ├── week      周报表(ISO 周,周一为起点)
    └── range     自定义范围报表

六、详细命令用法

所有时间参数格式:YYYY-MM-DD HH:mm,不指定时默认取当前时间。


primary start — 开始新主状态

node cli.js primary start <name> [category] [taskAttr] [remark] [--at <time>]

如果当前有进行中的主状态,会原子性地关闭它再开启新的。--at 指定的时间点同时作为旧状态的结束时间和新状态的开始时间。

node cli.js primary start "写架构文档" "工作" "目标任务"
node cli.js primary start "开会" "工作" "支撑任务" "周例会" --at "2026-04-17 10:00"

失败条件: --at 晚于当前时间;新区间与历史记录重叠。


primary switch — 切换主状态

primary start 完全相同,语义上强调"切换"。

node cli.js primary switch "代码审查" "工作" "支撑任务"

primary stop — 结束当前主状态

node cli.js primary stop [--at <time>]
node cli.js primary stop
node cli.js primary stop --at "2026-04-17 12:30"

失败条件: 没有进行中的主状态;--at 晚于当前时间或早于开始时间。


primary current — 查看当前状态

显示当前进行中的主状态及所有进行中的上下文状态。

node cli.js primary current
# [进行中] 主状态: 写架构文档 (已持续 42 分钟)
#   分类: 工作 | 属性: 目标任务 | 备注:
# [进行中] 上下文状态:
#   - [3] 听音乐 [音频] (已持续 20 分钟)

primary add — 补记历史区间

node cli.js primary add <startTime> <endTime> <name> [category] [taskAttr]

直接创建一条完整的历史记录(closed block),不影响当前进行中的状态。区间不能与任何已有记录重叠。

node cli.js primary add "2026-04-17 09:00" "2026-04-17 10:30" "晨间阅读" "学习" "目标任务"
node cli.js primary add "2026-04-16 23:00" "2026-04-17 01:00" "夜间工作" "工作" "目标任务"

primary list — 列出近期主状态

列出最近 20 条主状态记录(按开始时间倒序)。

node cli.js primary list
# [5] 代码审查 (工作) | 04-17 14:00 -> 04-17 15:30
# [4] 写架构文档 (工作) | 04-17 10:30 -> 04-17 14:00
# ...

context start — 开启上下文

node cli.js context start <name> [type] [--at <time>]

type 可选值:思考 / 移动 / 音频 / 背景事务(默认:背景事务

node cli.js context start "听音乐" "音频"
node cli.js context start "通勤" "移动" --at "2026-04-17 09:00"

context stop — 结束上下文

按 ID:

node cli.js context stop 3

按名称关闭最新的同名上下文:

node cli.js context stop --name "听音乐" --latest

失败条件: 找不到对应 ID 或该 ID 已关闭;找不到名为该名称且进行中的上下文。


context list — 列出上下文

node cli.js context list           # 列出所有(含历史)
node cli.js context list --open    # 只列进行中的
# [1] 听音乐 (音频) | 04-17 10:30 -> 进行中
# [2] 听音乐 (音频) | 04-17 13:00 -> 进行中

routine add — 新增弹性开销模板

node cli.js routine add <name> --category <cat> --min <分钟> --max <分钟> [--no-feedback]
node cli.js routine add "睡眠" --category "生活维护" --min 390 --max 510
node cli.js routine add "运动" --category "生活维护" --min 30 --max 90 --no-feedback

约束: name 不能重复;min ≥ 0;max ≥ min。


routine list / enable / disable / update

node cli.js routine list

node cli.js routine disable 1        # 停用,不再参与报表反馈
node cli.js routine enable 1         # 重新启用

node cli.js routine update 1 --min 400 --max 480 --no-feedback
node cli.js routine update 2 --name "冥想" --category "休息"

update 只更新指定的字段,其余保持不变。


report day — 日报表

node cli.js report day                        # 今天
node cli.js report day --date 2026-04-17      # 指定日期

report week — 周报表

以 ISO 周(周一为起点)为范围。

node cli.js report week                       # 本周
node cli.js report week --date 2026-04-14     # 该日期所在的周

report range — 自定义范围报表

node cli.js report range --from "2026-04-17 00:00" --to "2026-04-17 18:00"
node cli.js report range --from "2026-04-01 00:00" --to "2026-04-30 23:59"

七、报表说明

每次 report 输出 7 个部分:

=== 报表 [2026-04-17 00:00] 至 [2026-04-17 22:30] ===
生成时间: 2026-04-17 22:30:15

1. 记录覆盖摘要       — 总时长、已记录、未记录、覆盖率
2. 主要时间去向       — 按活动名称汇总,降序排列
3. 分类汇总           — 工作/学习/休息等大类分布
4. 任务属性汇总       — 目标任务/支撑任务等维度累计
5. 推导间隙           — 最大的几个未记录空白段
6. 专注反馈           — 基于目标任务、漂移占比的自动评价
7. 固定开销反馈       — 与 active 的 routine 模板对比实际时长

跨天 Block 的裁剪(Clipping)

查询范围 [Q_start, Q_end] 与某条记录 [B_start, B_end] 的交集才计入报表:

实际开始 = max(Q_start, B_start)
实际结束 = min(Q_end,   B_end)

例:记录跨越 2026-04-16 23:00 → 2026-04-17 01:00,在 2026-04-17 日报中只计入 00:00 → 01:00 共 60 分钟。

Open Block 的处理

若报表范围覆盖当前时间,进行中的主状态会被当作虚拟闭合块处理:

虚拟结束时间 = min(当前时刻, Q_end)

Derived Gap 的推导

[Q_start, Q_end] 出发,按时间顺序遍历所有裁剪后的主状态记录,找到块与块之间(以及首尾)的空白区间,即为 Derived Gap。报表显示其中最大的 3 个。

专注反馈规则

| 条件 | 提示 | |------|------| | 查询范围 ≥ 8 小时,目标任务 < 2 小时 | 红色提醒:目标任务偏少 | | 目标任务 ≥ 2 小时 | 绿色:投入良好 | | 漂移/分心 > 1 小时 | 红色提醒:漂移时间过多 | | 漂移/分心 ≤ 1 小时 | 绿色:控制合理 |


八、常见工作流示例

工作流 1:一天中不断切换主状态

# 早上开始工作
node cli.js primary start "晨间阅读" "学习" "目标任务"

# 切换到工作,自动关闭上一个
node cli.js primary switch "写代码" "工作" "目标任务"

# 有个会议,补记精确时间
node cli.js primary switch "开会" "工作" "支撑任务" "" --at "2026-04-17 10:00"

# 会议结束
node cli.js primary stop --at "2026-04-17 11:30"

# 继续写代码
node cli.js primary start "写代码" "工作" "目标任务"

# 下班,查看今天的日报
node cli.js report day

工作流 2:同时记录上下文状态

# 开始工作
node cli.js primary start "写代码" "工作" "目标任务"

# 同时开启背景音乐
node cli.js context start "Lo-fi 音乐" "音频"

# 中途去咖啡馆,主状态不变,上下文改变
node cli.js context stop --name "Lo-fi 音乐" --latest
node cli.js context start "通勤" "移动"

# 到了咖啡馆,结束通勤
node cli.js context stop 2

# 查看当前状态
node cli.js primary current

工作流 3:日终看报表 + 补录遗漏

# 发现中午有段时间忘记记录了,补录
node cli.js primary add "2026-04-17 12:00" "2026-04-17 13:00" "午饭休息" "休息" "休息恢复"

# 看今日报表
node cli.js report day --date 2026-04-17

# 看本周报表
node cli.js report week

# 看指定时段
node cli.js report range --from "2026-04-17 09:00" --to "2026-04-17 18:00"

九、测试与验证

参见 TESTING.md,其中包含 5 组 smoke test:

  1. 主状态流转(start → switch → stop)
  2. 防重叠约束(overlapping add should fail)
  3. 上下文并发与条件关闭
  4. 跨天报表裁剪
  5. 弹性模板管理(routine lifecycle)

快速跑一遍(清库后执行):

rm -f ~/.local/share/timelog/timelog.sqlite

node cli.js primary start "写架构文档" "工作" "目标任务"
node cli.js primary switch "代码重构" "工作" "目标任务"
node cli.js primary stop
node cli.js primary list

十、AI / 脚本调用注意事项

timelog 可被 AI 助手或 shell 脚本直接调用,以下行为已内置:

颜色输出

当 stdout 不是交互式终端(管道、重定向、AI 工具调用)时,ANSI 颜色码自动关闭,输出为纯文本。交互式终端下颜色保持不变。

# 纯文本输出(无 ANSI 码)
node cli.js primary list | cat

# 交互式终端下有颜色
node cli.js primary list

退出码

| 退出码 | 含义 | |--------|------| | 0 | 命令成功 | | 1 | 命令失败(错误信息输出到 stderr) |

失败场景包括:无效时间格式、时间在未来、区间重叠、找不到目标记录、无效参数等。

node cli.js primary add "2026-01-01 10:00" "2026-01-01 09:00" "测试"
echo $?   # 输出 1

时间格式

所有命令输出的时间均使用完整格式 YYYY-MM-DD HH:mm,不会出现缺少年份的 MM-DD HH:mm,方便跨天、跨年场景下的准确解析。


十一、当前边界 / 已知限制

| 项目 | 说明 | |------|------| | Routine 匹配策略 | 报表中 Routine 反馈按活动名称匹配(routine.name == block.name),这是临时策略,不够灵活 | | 无多端同步 | 数据存储在本地平台默认应用数据目录(Linux: $XDG_DATA_HOME/timelog/timelog.sqlite;macOS: ~/Library/Application Support/timelog/timelog.sqlite;Windows: %LOCALAPPDATA%\\timelog\\timelog.sqlite),不涉及云同步或跨设备访问 | | CLI 为唯一入口 | 目前只有命令行界面,无 Web UI 或 API | | Context Block 无报表聚合 | 上下文状态目前不参与报表时长统计,仅作状态查询 | | task_attr 不做枚举校验 | 命令行输入的任务属性值不会被校验是否合法,拼写错误会静默写入 | | 时区 | 内部全程使用本地时间 + UTC ISO-8601 存储,跨时区场景未测试 |