touch-grass
🌿 touch-grass
提醒您去户外走走的 Claude Code 插件。
感知天气 · 感知日落 · 感知会话 · 绝不打断您的工作流。
为什么会有这个项目
番茄钟会打断你的工作流。日历提醒常被忽略。离开编辑器的最佳时机是一个动态目标,取决于天气、时间、你的连续记录以及你当前正在处理的事情——而这些是死板的间隔计时器所不知道的。
你的 AI 编程智能体已经知道你何时处于自然停顿状态。 它完成了功能。它在等你回答问题。测试通过了。那是提醒你的最佳时刻——而不是每 25 分钟准时提醒一次。
touch-grass 将你的智能体变成一个有情境意识的休息伙伴。SessionStart 钩子在每次会话开始时为其提供实时天气和日落时间。一项技能教会它“虎妈”式的语气(温暖、具体、绝不唠叨)。MCP 服务器允许它记录你实际去户外的时间。你保持了工作流,它让你保持自律。
功能特点
就像番茄钟,但它了解天气、日落时间和你的编程连续记录——并且它会与你的 AI 智能体对话,而不是直接打断你。
SessionStart 钩子:每次 Claude Code 会话开始时,将实时天气、日落时间和连续记录状态注入到智能体的上下文中。
MCP 服务器:提供四个你的智能体(Claude Code、Cursor、Claude Desktop、Codex)可以按需调用的工具。
技能:教会智能体何时提醒、何时保持安静,以及使用什么语气(虎妈式,而非说教式)。
它是 Claude Code 的番茄钟替代品,适合那些宁愿让编程智能体提醒自己去户外,也不愿被屏幕遮挡计时器打断工作流的人。
安装
Claude Code(完整体验 — 钩子 + MCP + 技能):
/plugin install nalediym/touch-grass就是这样。开启一个新会话 — 钩子触发,上下文注入,你的智能体将接管后续操作。
git clone https://github.com/nalediym/touch-grass
cd touch-grass/plugin/mcp-server && npm install然后添加到你的客户端 MCP 配置中:
{
"mcpServers": {
"touch-grass": {
"command": "node",
"args": ["/absolute/path/to/touch-grass/plugin/mcp-server/index.mjs"]
}
}
}你将获得四个 MCP 工具,但失去了 Claude Code 特有的 SessionStart 钩子。你的智能体只会在你明确询问时才会提及户外活动。
工作原理
flowchart LR
A[Claude Code<br/>session starts] --> B[SessionStart hook fires]
B --> C[ip-api.com<br/>location]
B --> D[open-meteo.com<br/>weather + sunset]
B --> E[~/.touch-grass/state.json<br/>streak + sessions]
C --> F[Context injection]
D --> F
E --> F
F --> G[Agent<br/>decides when to nudge]
G -.calls.-> H[MCP tools]
H --> E会话开始时,钩子脚本运行。它通过你的公共 IP(缓存 24 小时)检测你的位置,从 open-meteo 获取当前天气和日落时间,读取你的本地连续记录文件,并为智能体合成一个简短的上下文块。智能体读取它,并在自然停顿(功能完成、Bug 修复、等待输入)时,根据实际情况用合适的语言提醒你出去走走。
当你确认去户外后,智能体会通过 MCP 服务器调用 log_touch_grass,这会增加本地状态文件中的连续记录天数。
MCP 工具
工具 | 用途 | 返回值 |
| 天气、温度、距离日落的分钟数以及用户的连续记录状态。决策上下文。 | 包含 |
| 随机活动推荐,按时间加权。黄金时刻会有特定的日落建议。 | 纯文本,如 |
| 记录用户已去户外。更新连续记录。仅在确认后调用。 | 带有新连续记录计数的确认信息 |
| 原始会话遥测和连续记录历史。 | JSON 块 |
所有四个工具都可以从任何兼容 MCP 的智能体调用。在 Claude Code 中,智能体主要通过钩子注入的上下文来使用它们——你很少需要手动调用。
示例提示词
该插件在后台运行,但如果你想主动询问,以下表达方式效果很好:
"我现在应该去户外走走吗?"
"我的连续记录是多少?"
"在日落前提醒我出去走走。"
"我刚去散步了,记录一下。"
"外面天气好吗?"
隐私
一切以本地优先。
存储在你的机器上:
~/.touch-grass/state.json(连续记录、会话计数、上次户外活动日期)和~/.touch-grass/config.json(缓存位置、天气阈值)。离开你的机器: 你的公共 IP 每 24 小时发送一次到
ip-api.com以解析城市坐标,这些坐标在每次会话开始时发送到api.open-meteo.com以获取天气和日落时间。绝不离开你的机器: 你的连续记录、活动笔记、编程计划、提示词,以及 Claude Code 会话中的任何内容。
没有账户。没有 API 密钥。没有遥测。没有分析。没有身份验证。如果你想完全禁用网络访问,请在 ~/.touch-grass/config.json 中手动固定 "location",IP 查询将永远不会触发。
配置
{
"location": {
"lat": 40.7128,
"lon": -74.0060,
"city": "New York",
"timezone": "America/New_York",
"fetchedAt": 9999999999999
},
"niceWeatherThresholdC": 15,
"breakIntervalHours": 2,
"enabled": true,
"customActivities": [
{ "label": "walk to the corner store", "emoji": "🛒" },
{ "label": "sit on the fire escape", "emoji": "🪜" }
]
}键 | 默认值 | 描述 |
| auto (ip-api) | 固定到特定位置。将 |
|
| 低于此温度(°C)的天气不被视为“宜人”。 |
|
| 连续编码超过此小时数后,提醒会变得更坚定。 |
|
| 设置为 |
|
| 用你自己的列表替换默认活动列表。每个条目都是 |
故障排除
手动运行钩子以确认其工作正常:
node plugin/hooks/session-start.mjs你应该看到一个包含 hookSpecificOutput.additionalContext 的 JSON 对象,其中包含提醒信息。如果 additionalContext 是空字符串,说明钩子无法连接到 ip-api.com 或 open-meteo.com — 请检查你的网络。如果钩子正常但 Claude Code 从未调用它,说明插件未正确连接 — 在新会话中重新运行 /plugin install nalediym/touch-grass。
检查 ~/.touch-grass/state.json。sessionStart、lastSessionStart 和 totalCodingSessions 字段会在每次钩子运行时更新。如果 sessionStart 比你最近一次调用 claude 的时间早,说明钩子没有运行。
可以。在 ~/.touch-grass/config.json 中手动固定你的位置:
{
"location": {
"lat": 40.7128,
"lon": -74.0060,
"city": "New York",
"timezone": "America/New_York",
"fetchedAt": 9999999999999
}
}较高的 fetchedAt 时间戳可防止 24 小时缓存过期,因此 IP 查询永远不会触发。天气仍将从 open-meteo.com 获取。
在 ~/.touch-grass/config.json 中设置 "enabled": false。钩子仍会写入会话遥测,但会发出空上下文,因此智能体将停止显示户外提醒。
删除或编辑 ~/.touch-grass/state.json。该文件将在下一次会话中以默认值重新创建。
/plugin uninstall touch-grass
rm -rf ~/.touch-grass~/.touch-grass 目录仅保存你的状态和缓存位置 — 可以安全删除。
开发
git clone https://github.com/nalediym/touch-grass
cd touch-grass/plugin/mcp-server && npm install
# Test the hook directly (outputs JSON context)
node ../hooks/session-start.mjs
# Test the MCP server with the inspector
npx @modelcontextprotocol/inspector node ./index.mjs三个部分:
plugin/hooks/session-start.mjs— 无依赖 Node 脚本。由 Claude Code 在会话开始时调用。输出 JSON 到 stdout。plugin/mcp-server/index.mjs— MCP 服务器。使用@modelcontextprotocol/sdk。stdio 传输。plugin/lib/grass.mjs和plugin/lib/nudge.mjs— 共享逻辑(天气、日落、状态、提醒文本)。
钩子和 MCP 服务器从同一个状态文件读取,因此它们保持同步。
相关
open-meteo.com — 免费、无需密钥的天气 API
ip-api.com — 免费、无需密钥的 IP 地理定位
许可证
MIT · 在阴凉处构建。
支持
touch-grass 是免费且 MIT 许可的。如果它帮助你离开了屏幕,请考虑支持它:
在 Polar 上支持 → — 9 美元一次性捐赠。你的名字将出现在支持者列表中,你将获得优先处理问题的权利,并解锁配置中的自定义活动列表。
支持者
成为第一个支持者。在 Polar 上支持 →
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/nalediym/touch-grass'
If you have feedback or need assistance with the MCP directory API, please join our Discord server