1. 项目概述一个追踪技能成长的利器最近在GitHub上看到一个挺有意思的项目叫mvanhorn/last30days-skill。光看名字你大概能猜到它和“技能”、“最近30天”有关。没错这是一个用来追踪和可视化你过去30天里在特定技能上投入时间的工具。简单来说它就像一个为你个人技能成长量身定制的“仪表盘”。在当今这个信息爆炸、知识迭代飞快的时代无论是程序员、设计师、作家还是任何领域的从业者持续学习已经成了生存的刚需。我们常常会心血来潮地学习新东西比如“这个月要学好Python”、“下个月要精通Figma”但结果往往是三天打鱼两天晒网一个月过去了回头一看好像啥也没干成时间都去哪儿了last30days-skill这个项目就是为了解决这个痛点而生的。它不帮你学习但它帮你“看见”你的学习。通过一个简洁的命令行工具你可以记录每天在某个技能上花了多少时间然后它会生成一个直观的图表让你清晰地看到过去30天的努力轨迹。这个工具特别适合那些有明确技能提升目标、喜欢量化自我、或者正在进行“100天打卡”挑战的朋友。它用最轻量的方式把抽象的“学习”变成了具体的、可度量的“时间投入”这种可视化反馈本身就是一种强大的激励。接下来我就带你深入拆解这个项目的设计思路、核心实现并分享如何把它用起来甚至根据自己的需求进行定制。2. 项目核心思路与设计哲学2.1 为什么是“30天”和“技能”项目的核心设计理念非常聚焦追踪单一技能在最近一个时间窗口内的投入情况。这里有两个关键维度“30天”和“技能”。首先为什么选择“30天”作为时间窗口这背后有很强的行为心理学依据。一个月约30天是一个天然的习惯养成周期也是大多数人制定短期计划如月度目标的常用单位。时间太短如7天波动性太大看不出趋势时间太长如90天反馈周期过长容易让人失去坚持的动力。30天正好是一个既能反映持续努力又能及时获得反馈的“黄金周期”。它让你能在一个相对完整的周期内评估自己为某个技能付出的真实努力程度。其次聚焦于“技能”。市面上有很多时间追踪工具如Toggl, RescueTime它们功能强大可以追踪你在各个应用、网站甚至项目上的时间。但last30days-skill反其道而行之它极度简化只关心一件事你在某个特定技能上花了多少时间。比如“Python编程”、“吉他练习”、“英语阅读”。这种设计强迫你去定义和聚焦避免了泛泛的“我今天学习了”这种模糊记录。当你为时间打上“技能”标签时你就在有意识地进行“刻意练习”而不仅仅是消磨时间。这种极简主义的设计哲学使得工具的学习和使用成本极低。你不需要复杂的项目分类、客户账单功能你只需要回答两个问题1. 我今天练习了什么技能2. 我练了多久剩下的交给工具来帮你呈现。2.2 数据存储与可视化的轻量化抉择作为一个命令行工具last30days-skill在技术选型上充分体现了“够用就好”的原则。它通常采用纯文本文件如JSON或CSV来存储每次的记录。每条记录可能包含技能名称、日期、持续时间分钟或小时。例如[ {skill: Python, date: 2023-10-27, duration_minutes: 60}, {skill: 吉他, date: 2023-10-27, duration_minutes: 30} ]注意使用纯文本文件存储意味着数据完全掌握在你自己手中没有隐私泄露到第三方服务器的风险。但这也要求你做好文件的备份防止误删。可视化部分是项目的亮点。它一般会调用像matplotlib(Python) 或Chart.js(JavaScript) 这样的图表库根据过去30天的数据生成一个趋势图。X轴是日期Y轴是累计时间。图表可能会用柱状图显示每日投入用折线图显示累积趋势。这种视觉化呈现其心理效用远超一堆枯燥的数字。你能一眼看出哪几天偷懒了哪几天爆发了整体趋势是在上升还是下降。这种即时、直观的反馈是坚持习惯的巨大动力源。整个工具的运行流程可以概括为记录CLI命令 - 存储本地文件 - 聚合按技能、按日期 - 可视化生成图表 - 输出终端显示或图片文件。逻辑清晰各模块耦合度低这也为后续的扩展和定制留下了空间。3. 核心功能拆解与实操上手3.1 安装与基本命令假设项目是用Python写的这是一种常见且合理的假设我们可以模拟一下它的安装和使用流程。通常这类工具会发布到PyPIPython包索引你可以用pip一键安装。# 安装工具 pip install last30days-skill # 或者从GitHub直接安装开发版 pip install githttps://github.com/mvanhorn/last30days-skill.git安装完成后核心命令一般不会太多可能就两三个记录时间这是最常用的命令。# 记录今天在“Python”上投入了90分钟 last30days log Python 90 # 也可以指定日期比如补记昨天的 last30days log --date 2023-10-26 Guitar 45这个命令的背后工具会打开本地的数据文件比如在~/.last30days/data.json追加一条新记录。它会自动处理重复技能名的合并同一天同一技能的时间累加和日期格式化。生成报告/图表# 查看“Python”技能过去30天的报告 last30days report Python # 生成所有技能的报告 last30days report --all执行这个命令时工具会读取数据文件。过滤出指定技能或所有技能在过去30天内的记录。按日期聚合计算每日总时长。调用绘图库在终端内用字符画如果支持输出一个简易图表或者更常见的是生成一个HTML文件或图片如last30days_Python.png并用你的默认浏览器打开。可能有的辅助命令# 列出所有记录过的技能 last30days list-skills # 删除某条记录按索引或日期 last30days delete --id 5实操心得刚开始使用时最容易忘记记录。建议将记录命令和你学习行为的“结束动作”绑定。比如每次关闭编程IDE后就立即在终端里敲下记录命令。或者更进阶一点可以写一个简单的脚本在你关闭某个特定软件如PyCharm时自动弹出记录提示。3.2 数据文件结构与维护理解工具如何存储数据对于排查问题和进行高级操作至关重要。如前所述数据很可能存储为一个JSON文件。它的结构设计直接影响着功能的实现。一个健壮的数据结构可能长这样{ version: 1.0, records: [ { id: a1b2c3d4, skill: Python, date: 2023-10-27, duration: 90, unit: minutes, notes: 学习了异步编程asyncio模块, created_at: 2023-10-27T22:30:00Z } ] }id: 每条记录的唯一标识用于精确修改或删除。skill: 技能名称是查询和分组的核心键。date: 记录的日期ISO 8601格式保证排序和计算无误。durationunit: 持续时间及其单位支持灵活记录可以是25分钟的“番茄钟”也可以是2小时的“沉浸式学习”。notes: 可选的备注字段。强烈建议填写一周后你可能忘了这90分钟具体学了什么一句简单的备注如“重构了XX模块”、“解决了XX报错”能让这段时间的价值清晰再现。created_at: 记录创建的时间戳用于审计。维护建议定期备份你的数据文件是核心资产。可以把它放入云盘同步文件夹如Dropbox, iCloud Drive或者用Git进行版本管理git init在数据目录下定期git commit。用Git管理还有一个好处你可以看到自己学习习惯的“历史变更”。技能名称归一化避免出现“Python”、“python”、“Python编程”这种同义不同名的技能这会导致数据分散。定下一个标准并始终坚持比如全部用英文、首字母大写。数据清理如果工具没有提供可以手动或用脚本定期检查数据文件合并同一天同一技能的重复记录如果因误操作产生了多条。4. 可视化方案深度解析与定制4.1 默认图表解读与价值工具生成的图表是其灵魂所在。一份好的可视化报告应该能让你在10秒内获得关键洞察。典型的输出可能包含以下元素每日投入柱状图最直观的部分。每个柱子代表一天在目标技能上的总投入时间。柱子高低一目了然。你会立刻发现“零投入”的空窗日这比看日历更触目惊心从而产生“明天一定要补上”的补偿心理。累积趋势线在柱状图基础上叠加的一条线显示从30天前到今天的累计总时间。这条线的斜率就是你的“平均每日投入”。如果它持续平稳上升说明你坚持得很好如果变得平缓就是警报。关键统计摘要图表旁边或下方通常会文字输出过去30天总时间例如“总计35小时”。平均每日时间例如“日均1.17小时”。投入天数例如“有记录的天数24/30”。这个比例很重要它反映了你的连续性而不仅仅是总量。最长连续投入天数这是衡量习惯稳固性的黄金指标。这些数据结合起来就构成了一份完整的“技能学习体检报告”。它不再依赖于模糊的感觉“我这个月挺努力的”而是给出了客观、量化的证据。4.2 如何定制你的专属图表开源工具的魅力在于你可以按需修改。如果你对默认的图表风格或信息不满足完全可以自己动手。这通常需要你有一点编程基础主要是Python。假设项目使用matplotlib绘图它的绘图代码可能在一个独立的模块里比如chart.py。你可以找到这个文件进行修改。常见定制需求与实现思路更改颜色主题你可能觉得默认的蓝色柱子不好看想换成更符合你终端或个人喜好的配色。# 在绘图代码中找到 bar 函数调用 ax.bar(dates, hours, color#2E86AB) # 将默认颜色改为一种深蓝色 # 或者使用渐变色 colors plt.cm.viridis(np.linspace(0.5, 1, len(dates))) ax.bar(dates, hours, colorcolors)添加目标线如果你想挑战日均学习2小时可以在图表上添加一条水平虚线作为目标线直观对比。target_hours_per_day 2 ax.axhline(ytarget_hours_per_day, colorr, linestyle--, linewidth1, labelf目标 (日均{target_hours_per_day}h)) ax.legend() # 显示图例突出显示周末将周六周日的柱子用不同颜色标出看看自己的学习节奏是否受工作日影响。import matplotlib.dates as mdates # 判断每天是否是周末 weekend_days [i for i, d in enumerate(dates) if d.weekday() 5] # 5周六6周日 weekday_days [i for i, d in enumerate(dates) if d.weekday() 5] # 分别绘制 ax.bar(np.array(dates)[weekday_days], np.array(hours)[weekday_days], colorb, label工作日) ax.bar(np.array(dates)[weekend_days], np.array(hours)[weekend_days], colorg, label周末)输出更多格式默认可能只生成PNG或显示在屏幕。你可以修改代码让其同时生成PDF方便打印归档或SVG矢量图无限放大不模糊。# 在 plt.show() 或 plt.savefig() 附近 plt.savefig(my_skill_report.pdf, formatpdf, dpi300, bbox_inchestight) plt.savefig(my_skill_report.svg, formatsvg)注意事项修改源代码前最好先Fork原项目仓库到自己的GitHub账号下然后在自己的副本上修改。这样你可以随时同步原项目的更新也能管理自己的定制版本。修改时注意阅读相关的代码注释理解数据流数据如何从存储文件传递到绘图函数。5. 高级用法与生态集成5.1 自动化记录告别手动输入手动记录始终是个负担容易遗忘。理想的状态是“无感记录”。我们可以通过一些自动化手段来逼近这个目标。场景一与特定开发环境联动如果你练习的是编程技能可以尝试在IDE或编辑器中集成。例如使用VS Code的插件系统或任务功能。你可以写一个简单的Python脚本监听项目文件夹的活动或者利用编辑器提供的“会话时间”API在关闭编辑器时自动弹窗或发送通知询问本次编码时长并调用last30days log命令。场景二基于日历或时间块App如果你使用日历如Google Calendar或时间块规划App如Sorted³你可以在这些工具中为“技能学习”创建固定事件。然后写一个定时脚本比如每天睡前运行读取日历中标记为“Python学习”的事件计算总时长并自动调用CLI工具记录。这样你的计划日历和复盘last30days就打通了。场景三使用系统级自动化工具对于Mac用户可以利用AppleScript或更强大的Hammerspoon对于Windows用户可以使用AutoHotkey或PowerShell脚本Linux用户则可以用cron定时任务加上shell脚本。这些工具可以监控你特定应用的窗口焦点。例如当检测到PyCharm或VS Code窗口处于活动状态超过一定时间比如25分钟并且在此期间没有长时间的非活动中断就认为进行了一次“番茄钟”的学习自动记录25分钟到“编程”技能下。一个简单的cron shell脚本示例# 1. 创建一个脚本 ~/auto_log_skill.sh #!/bin/bash # 检测“代码编辑器”是否在前台运行超过30分钟这里需要借助其他工具如xprintidle获取空闲时间逻辑较复杂仅示意 # 假设我们通过某种方式判断出本次有效学习时长为 $DURATION 分钟 SKILLProgramming # 调用 last30days 工具记录日期默认为今天 /usr/local/bin/last30days log $SKILL $DURATION # 2. 通过cron定时执行例如每30分钟检查一次 # crontab -e 添加 */30 * * * * /bin/bash /home/yourname/auto_log_skill.sh警告自动化记录的关键在于准确性。过于激进的全自动记录比如只要软件打开就计时会产生大量噪音数据比如挂着编辑器刷网页的时间。因此半自动化自动检测手动确认或基于明确事件如日历事件的自动化是更可靠的选择。5.2 数据导出与二次分析last30days-skill工具本身提供的分析是基础的。你的数据宝藏可以挖掘出更多洞见。这就需要将数据导出用更强大的工具如Python的Pandas, Jupyter Notebook进行分析。导出数据通常工具会提供导出命令或者数据文件本身就是JSON/CSV可以直接读取。# 假设工具支持导出 last30days export --format csv my_skill_data.csv在Jupyter Notebook中进行探索性分析import pandas as pd import matplotlib.pyplot as plt # 加载数据 df pd.read_csv(my_skill_data.csv, parse_dates[date]) df[hours] df[duration_minutes] / 60 # 转换为小时 # 1. 分析各技能总投入时间占比 skill_summary df.groupby(skill)[hours].sum().sort_values(ascendingFalse) skill_summary.plot.pie(autopct%1.1f%%, figsize(8,8)) plt.title(各技能总时间投入分布) plt.ylabel() # 隐藏y轴标签 plt.show() # 2. 分析每周学习节奏看看周几最努力 df[day_of_week] df[date].dt.day_name() df[week_number] df[date].dt.isocalendar().week weekly_pivot df.pivot_table(indexday_of_week, columnsweek_number, valueshours, aggfuncsum, fill_value0) # 按星期顺序排序 day_order [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday] weekly_pivot weekly_pivot.reindex(day_order) weekly_pivot.plot(kindbar, figsize(12,6)) plt.title(每周各天学习时间热力图按周聚合) plt.xlabel(星期) plt.ylabel(学习时长 (小时)) plt.legend(title第几周) plt.show() # 3. 计算学习效率趋势假设有“notes”字段标记了关键产出 # 可以结合笔记中的关键词如“完成项目”、“解决bug”来定义“有效学习时间”进行更深入的分析。通过这样的二次分析你可能会发现意想不到的模式比如周末下午效率最高或者学习某个技能的前10小时进步最快之后会进入平台期。这些洞见能帮助你更科学地规划学习计划。6. 常见问题与故障排查实录即使是一个简单的工具在实际使用中也会遇到各种问题。下面是我在长期使用和模拟类似工具时遇到的一些典型情况及解决方法。6.1 安装与运行问题问题1command not found: last30days原因安装成功后命令行工具的可执行文件路径没有被添加到系统的PATH环境变量中。排查确认安装是否真的成功pip show last30days-skill。找到可执行文件的安装位置。对于pip安装的Python工具它通常在~/.local/bin(Linux/macOS) 或%APPDATA%\Python\Scripts(Windows) 下。将该路径添加到PATH。Linux/macOS编辑~/.bashrc或~/.zshrc添加export PATH$HOME/.local/bin:$PATH然后执行source ~/.bashrc。Windows在系统属性 - 高级 - 环境变量中编辑用户变量的Path添加上面的路径。快速验证重新打开终端输入last30days --help看是否出现帮助信息。问题2运行命令时报Python模块错误如ModuleNotFoundError: No module named click原因工具依赖的Python库没有正确安装。可能是在虚拟环境中安装的工具但你在全局环境或其他虚拟环境中运行。解决确保你在安装工具的同一個Python环境下运行。如果你用了虚拟环境venv, conda请先激活它。尝试重新安装pip install --force-reinstall last30days-skill。--force-reinstall会确保所有依赖也被正确处理。检查是否有多个Python版本冲突。使用which python和which pip确认你正在使用的版本。6.2 数据记录与查看问题问题3记录时间后report命令看不到最新数据原因1时区问题。工具记录的日期是UTC而你查看时用的是本地时间可能还在“昨天”。解决检查工具是否支持时区设置。通常可以在记录或报告时指定时区如last30days log --tz Asia/Shanghai Python 60。或者查看数据文件确认记录的date字段是否正确。原因2数据文件损坏或格式错误。如果你手动编辑过JSON文件一个多余的逗号或引号错误就会导致解析失败。解决使用JSON验证工具如在线JSON校验器检查你的数据文件。或者尝试用工具的备份功能如果有恢复。养成修改前备份的好习惯。问题4想合并或修改历史记录中的错误数据原因工具可能没有提供精细的编辑功能。解决直接编辑数据文件JSON。但务必小心先备份cp data.json data.json.backup使用能理解JSON格式的编辑器如VS Code, Sublime Text。找到对应的记录通过id或date和skill定位修改duration字段。保存后立即运行last30days report验证修改是否正确。如果工具提供了--dry-run或validate命令先用它检查数据完整性。问题5图表显示异常如乱码、布局错乱原因1中文字符显示为方框。解决这是matplotlib的字体问题。需要在绘图代码中指定中文字体。# 在绘图代码开头添加 import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, DejaVu Sans] # 指定默认字体SimHei为黑体 plt.rcParams[axes.unicode_minus] False # 解决负号显示问题原因2终端大小导致字符画图表换行混乱。解决尝试调整终端窗口的宽度或者使用工具提供的选项输出到文件如--output chart.html然后在浏览器中查看。6.3 习惯养成与心理调适问题6总是忘记记录怎么办对策将记录行为“锚定”到另一个稳固的日常习惯上。例如锚定到“关机”写一个脚本在电脑关机/休眠前自动弹出简易提示框询问今天的学习情况。锚定到“睡前复盘”在手机闹钟或日记App里设置睡前提醒花1分钟回顾并记录。降低记录门槛如果觉得开终端输命令麻烦可以写一个极简的GUI脚本双击运行后直接输入技能和分钟数即可。问题7看到连续几天的“零记录”柱子感到沮丧想放弃。心态调整这个工具是“镜子”不是“判官”。它的目的不是给你打分而是帮你客观地“看见”。空白的柱子不是失败而是信息。它告诉你“看这一块时间溜走了我们下次怎么把它抓住” 试着把关注点从“批判过去的缺失”转移到“规划未来的填充”。看到空白立刻想“明天哪个时间段我可以安排30分钟”问题8为了“刷数据”而低质量学习本末倒置。核心原则工具是仆人不是主人。记录时间是为了服务“有效学习”而不是让“学习”服务“记录”。解决方法善用“备注”notes字段。强迫自己每次记录时用一句话写下这期间完成的最具体的一件事例如“理解了Python装饰器的执行顺序”、“弹会了《成都》的前奏”。回顾时不仅看时间长度更要看这些“成果备注”。如果某天时长很长但备注空洞那可能就是低效时间。这能帮你把焦点从“坐了多久”拉回到“学会了什么”。7. 横向对比与同类工具选择last30days-skill定位非常精准但它并非唯一选择。了解生态位类似的工具能帮你做出更适合自己的选择。工具类型代表工具核心特点适合人群与last30days-skill对比全能型时间追踪Toggl Track, Clockify功能全面支持项目、客户、标签、团队协作有丰富报表和集成。自由职业者、团队管理者、需要详细时间账单的人。太重。对于只想追踪一两个技能的个人来说功能过剩设置复杂。自动追踪RescueTime, WakaTime后台自动记录你在电脑/手机上的活动分类统计。希望无感记录、了解数字生活习惯的人。不够聚焦。自动记录包含大量非学习时间如刷社交软件需要手动分类且无法记录离线技能如练琴、读书。习惯追踪AppHabitica, Loop Habit Tracker以打卡和养成习惯为核心游戏化或极简设计。需要多种习惯喝水、早睡、学习一起追踪的人。维度不同。习惯App关心“是否做了”而last30days-skill关心“做了多久”量化程度更深。手账/日记纸笔手账、Day One高度自由可记录时间、心得、情绪。喜欢书写、思考过程追求仪式感和深度复盘的人。不易统计。可视化、统计汇总困难数据难以量化分析。命令行极简追踪last30days-skill,timewarrior极简、快速、隐私、可脚本化。开发者、喜欢终端效率、注重隐私和数据控制、有定制需求的人。这正是它的赛道。last30days-skill在其中更强调“技能”维度和“30天”可视化。如何选择如果你是开发者或极客只想追踪少数几个核心技能的投入时间喜欢一切尽在掌控的感觉并且不介意偶尔敲敲命令那么last30days-skill这类命令行工具是你的绝佳选择。如果你需要追踪多种类型活动工作、学习、娱乐且希望自动进行那么 RescueTime 这类更合适。如果你需要基于时间记录向客户收费那么 Toggl 是不二之选。如果你的核心诉求是养成“做”的习惯而不是计量“做多久”那么习惯打卡App更好。说到底没有最好的工具只有最适合你当前场景的工具。last30days-skill的价值在于它在“技能量化”和“极简主义”这个交叉点上做得非常纯粹和出色。8. 项目扩展思路与未来想象作为一个开源项目last30days-skill有很大的扩展潜力。如果你对其功能感兴趣甚至想贡献代码以下是一些可能的方向1. 支持多技能对比图表目前可能主要针对单一技能生成报告。可以扩展report命令支持同时传入多个技能在一张图上用不同颜色的柱子或线条展示直观对比你在不同技能上的时间分配。这对于平衡多个学习目标的人非常有用。2. 集成提醒与目标设定增加goal子命令允许为技能设定周目标或月目标如“每周学习Python至少10小时”。工具可以在每周日生成报告时对比实际投入与目标并给出“达成”或“还需努力”的提示。甚至可以集成简单的系统通知如macOS的osascript或Linux的notify-send在进度落后时发送提醒。3. 数据同步与多端访问当前数据存储在本地。可以增加一个可选的同步功能将加密的数据文件同步到用户自己的云存储如WebDAV、Dropbox API、甚至Git仓库。再配套开发一个极其简单的手机端网页用于在手机上快速查看图表和进行简单的记录通过调用API。核心依然保持轻量同步只是可选项。4. 生成更丰富的报告格式除了趋势图可以增加生成“学习周报”或“月报”的功能。报告模板使用Markdown内容包含本月总时长、日均时长、最长连续天数、与上月对比、学习时间分布上午/下午/晚上、一句总结等。生成的Markdown可以直接粘贴到你的笔记软件如Obsidian, Logseq中形成连贯的学习日志。5. 开放数据接口API提供一个简单的本地HTTP API服务器比如运行在localhost:8080。这样其他脚本或工具如Alfred, Keyboard Maestro, 或者你自己写的其他自动化流程就可以通过发送HTTP请求来记录时间或查询数据极大地增强了可集成性。从我个人的使用体验来看这类工具最大的魅力不在于它本身功能有多强大而在于它为你提供了一个量化自我、建立反馈闭环的最小可行系统。当你开始记录数据就开始产生当你定期回顾图表反馈就形成了。这个简单的循环恰恰是克服惰性、实现持续成长的关键。它把遥远的年度目标拆解成了一个个可见的、可管理的30天冲刺。当你看到图表上的曲线总体向上那种由真实数据带来的成就感远比空洞的自我鼓励更有力量。