Skip to main content
Glama

🌿 touch-grass

提醒您去户外走走的 Claude Code 插件。

感知天气 · 感知日落 · 感知会话 · 绝不打断您的工作流。

CI License: MIT Stars Last commit MCP 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 工具

工具

用途

返回值

check_grass_conditions

天气、温度、距离日落的分钟数以及用户的连续记录状态。决策上下文。

包含 weather, sunset, isNice, minutesToSunset, state 的 JSON 块

suggest_activity

随机活动推荐,按时间加权。黄金时刻会有特定的日落建议。

纯文本,如 "🌅 欣赏日落"

log_touch_grass

记录用户已去户外。更新连续记录。仅在确认后调用。

带有新连续记录计数的确认信息

get_stats

原始会话遥测和连续记录历史。

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": "🪜" }
  ]
}

默认值

描述

location

auto (ip-api)

固定到特定位置。将 fetchedAt 设置为未来的时间戳以禁用自动刷新。

niceWeatherThresholdC

15

低于此温度(°C)的天气不被视为“宜人”。

breakIntervalHours

2

连续编码超过此小时数后,提醒会变得更坚定。

enabled

true

设置为 false 可在不卸载的情况下静默钩子。

customActivities

null

用你自己的列表替换默认活动列表。每个条目都是 { "label": "...", "emoji": "..." } 或纯字符串。支持者福利。

故障排除

手动运行钩子以确认其工作正常:

node plugin/hooks/session-start.mjs

你应该看到一个包含 hookSpecificOutput.additionalContext 的 JSON 对象,其中包含提醒信息。如果 additionalContext 是空字符串,说明钩子无法连接到 ip-api.comopen-meteo.com — 请检查你的网络。如果钩子正常但 Claude Code 从未调用它,说明插件未正确连接 — 在新会话中重新运行 /plugin install nalediym/touch-grass

检查 ~/.touch-grass/state.jsonsessionStartlastSessionStarttotalCodingSessions 字段会在每次钩子运行时更新。如果 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.mjsplugin/lib/nudge.mjs — 共享逻辑(天气、日落、状态、提醒文本)。

钩子和 MCP 服务器从同一个状态文件读取,因此它们保持同步。

相关

许可证

MIT · 在阴凉处构建。


支持

touch-grass 是免费且 MIT 许可的。如果它帮助你离开了屏幕,请考虑支持它:

在 Polar 上支持 → — 9 美元一次性捐赠。你的名字将出现在支持者列表中,你将获得优先处理问题的权利,并解锁配置中的自定义活动列表。

Polar GitHub Sponsors

支持者

成为第一个支持者。在 Polar 上支持 →

-
security - not tested
A
license - permissive license
-
quality - not tested

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