关于 clearshot
clearshot 是用于 UI 设计、实现、调试或评估的截图分析技能,将视觉观察整理为布局图、设计系统,并在需要实现时生成交互与布局蓝图。
主要功能
- 01按 5×5 网格映射截图布局
- 02记录元素状态与视觉尺寸
- 03提取颜色、字体和间距系统
- 04为 UI 重建生成实现蓝图
- 05提供截图对比与评审指导
适用场景
- 01将 UI 截图转为实现规格
- 02检查布局层级与视觉一致性
- 03比较两个 UI 版本
- 04为 UI 原型提供具体反馈
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ growthx-club/ build-sprint-skills --skill clearshot安装后在 Claude Code 中输入/clearshot确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitignore.npmignoreCHANGELOG.mdconfig.shinstall.shLICENSEpackage.jsonREADME.mdsetupVERSIONbin/cli.jsonboarding.shpicker.shtelemetry-setup.shupdate-prompt.shconvex/feedback.tshttp.tsschema.tstelemetry.tstsconfig.json详细介绍
前言
在进行任何分析之前,先运行此 bash 代码块:
# ─── Find skill directory (works from any install path) ───────
_CS_DIR=""
for _d in ".claude/skills/clearshot" ".agents/skills/clearshot" "$HOME/.claude/skills/clearshot" "$HOME/.agents/skills/clearshot"; do
[ -f "$_d/SKILL.md" ] && _CS_DIR="$(cd "$_d" && pwd)" && break
done
# fallback: search
[ -z "$_CS_DIR" ] && _CS_DIR="$(cd "$(dirname "$(find "$HOME/.claude" "$HOME/.agents" -name SKILL.md -path '*/clearshot/*' -print -quit 2>/dev/null)")" 2>/dev/null && pwd || echo "")"
_CS_VER=""
[ -n "$_CS_DIR" ] && [ -f "$_CS_DIR/VERSION" ] && _CS_VER="$(cat "$_CS_DIR/VERSION" | tr -d '[:space:]')"
_CS_STATE="$HOME/.clearshot"
mkdir -p "$_CS_STATE/analytics" "$_CS_STATE/feedback"
# ─── First-run detection ─────────────────────────────────────
_CS_FIRST_RUN="no"
[ ! -f "$_CS_STATE/config.yaml" ] && _CS_FIRST_RUN="yes"
# ─── Read config (only if it exists) ─────────────────────────
_CS_UPDATE_MODE="ask"
_CS_TEL="off"
_CS_TEL_PROMPTED="no"
if [ -f "$_CS_STATE/config.yaml" ]; then
_CS_UPDATE_MODE=$(grep -E '^update_mode:' "$_CS_STATE/config.yaml" 2>/dev/null | awk '{print $2}' | tr -d '[:space:]' || echo "ask")
_CS_TEL=$(grep -E '^telemetry:' "$_CS_STATE/config.yaml" 2>/dev/null | awk '{print $2}' | tr -d '[:space:]' || echo "off")
fi
[ -f "$_CS_STATE/.telemetry-prompted" ] && _CS_TEL_PROMPTED="yes"
# ─── Version check (only if user opted into updates) ─────────
# No network calls until config exists and user has chosen
if [ -n "$_CS_VER" ] && [ "$_CS_FIRST_RUN" = "no" ] && [ -d "$_CS_DIR/.git" ]; then
_CS_CACHE="$_CS_STATE/last-update-check"
_STALE=""
[ -f "$_CS_CACHE" ] && _STALE=$(find "$_CS_CACHE" -mmin +60 2>/dev/null || true)
if [ ! -f "$_CS_CACHE" ] || [ -n "$_STALE" ]; then
_CS_REMOTE=$(curl -sf --max-time 5 "https://raw.githubusercontent.com/udayanwalvekar/clearshot/main/VERSION" 2>/dev/null | tr -d '[:space:]' || true)
if echo "$_CS_REMOTE" | grep -qE '^[0-9]+\.[0-9.]+$' 2>/dev/null; then
if [ "$_CS_VER" != "$_CS_REMOTE" ]; then
if [ "$_CS_UPDATE_MODE" = "always" ]; then
cd "$_CS_DIR" && git pull origin main --quiet 2>/dev/null
_CS_VER="$(cat "$_CS_DIR/VERSION" 2>/dev/null | tr -d '[:space:]')"
echo "CS_AUTO_UPDATED: $_CS_VER"
echo "UP_TO_DATE $_CS_VER" > "$_CS_CACHE"
else
echo "UPGRADE_AVAILABLE $_CS_VER $_CS_REMOTE" > "$_CS_CACHE"
echo "CS_UPGRADE: UPGRADE_AVAILABLE $_CS_VER $_CS_REMOTE"
fi
else
echo "UP_TO_DATE $_CS_VER" > "$_CS_CACHE"
fi
fi
else
_CACHED="$(cat "$_CS_CACHE" 2>/dev/null || true)"
case "$_CACHED" in UPGRADE_AVAILABLE*)
if [ "$_CS_UPDATE_MODE" = "always" ]; then
cd "$_CS_DIR" && git pull origin main --quiet 2>/dev/null
_CS_VER="$(cat "$_CS_DIR/VERSION" 2>/dev/null | tr -d '[:space:]')"
echo "CS_AUTO_UPDATED: $_CS_VER"
echo "UP_TO_DATE $_CS_VER" > "$_CS_CACHE"
else
echo "CS_UPGRADE: $_CACHED"
fi
;;
esac
fi
fi
# ─── Session tracking ────────────────────────────────────────
_CS_SESSION_ID="$$-$(date +%s)"
_CS_TEL_START=$(date +%s)
echo "CS_FIRST_RUN: $_CS_FIRST_RUN"
echo "CS_SKILL_DIR: $_CS_DIR"
echo "CS_UPDATE_MODE: $_CS_UPDATE_MODE"
echo "CS_TEL_PROMPTED: $_CS_TEL_PROMPTED"
echo "CS_TELEMETRY: ${_CS_TEL:-off}"
echo "CS_SESSION_ID: $_CS_SESSION_ID"
echo "CS_TEL_START: $_CS_TEL_START"
echo "CS_VERSION: ${_CS_VER:-unknown}"
解读前言输出
如果 CS_FIRST_RUN 的值为 yes:
这是 clearshot 首次运行——尚无配置。进行任何分析之前,告知用户运行初始设置。简短说明,例如:
“clearshot 需要快速完成首次设置(回答两个问题,使用方向键和回车键):”
然后指示用户输入:! {CS_SKILL_DIR}/bin/onboarding.sh
使用前言输出中的实际 CS_SKILL_DIR 值(例如 ~/.claude/skills/clearshot 或 ~/.agents/skills/clearshot)。脚本会询问更新偏好和遥测设置、写入配置,并在几秒内完成。
用户运行脚本后,继续分析。如果用户拒绝,也继续进行——没有配置时不会进行网络调用。
如果出现 CS_AUTO_UPDATED:
该技能已自动更新。简要提及:“clearshot 已更新至 v{version}”,然后继续分析。无需采取任何操作。
如果 CS_UPGRADE 显示 UPGRADE_AVAILABLE <old> <new>:
用户设置了 update_mode: ask。告知用户有新版本可用,并指示他们运行交互式更新选择器:
“clearshot v{new} 已发布(你当前使用的是 v{old}):”
然后指示用户输入:! {CS_SKILL_DIR}/bin/update-prompt.sh {old} {new}
脚本会让用户选择“立即更新”或“始终更新”(后者也会将未来的更新模式切换为自动更新)。如果用户跳过,继续使用当前版本进行分析。
如果 CS_TEL_PROMPTED 的值为 no(但 CS_FIRST_RUN 也为 no):
用户已有配置,但不知为何跳过了遥测问题。告知他们运行:
! {CS_SKILL_DIR}/bin/telemetry-setup.sh
用户运行脚本后,继续分析。如果用户拒绝,也继续进行,并关闭遥测。
截图分析
当大模型查看截图并试图直接从像素得出代码(或反馈或描述)时,它会忽略空间关系、误读组件层级,并臆造设计细节。解决方法是在“查看图像”和“针对图像作答”之间建立结构化的中间表示。本技能提供的正是这一中间层。
检查条件
并非每张图像都需要使用本技能。
开始前先问两个问题:
-
这张图像是数字界面吗?(网站、应用、仪表板、模型图、线框图、Figma 导出图、带 UI 上下文的 CLI,以及显示了页面的浏览器 DevTools 都算。照片、表情包、独立图表、演示文稿幻灯片、文档、手写笔记则不算。)
-
对话是否与构建、调试、设计或评估 UI 有关?
三种结果:
- 两个问题的答案都是否定的:完全退出本技能。正常作答。不要提及此框架。
- 图像不是 UI,但对话确实与构建 UI 有关(例如“帮我构建一个有这张照片感觉的页面”):图像是灵感,而非规范。描述它传达的感受——氛围、质感、分量——然后继续。无需结构化分析。
- 图像是 UI,且对话与构建或评估有关:按照下面的分析层级继续。
分析层级
每次分析都兼顾事实和审美。不存在独立的“分析模式”或“定性模式”——每项观察都以具体细节(十六进制颜色值、像素尺寸)为依据,同时也包含主观感受(层级、分量、协调性)。这与资深设计师的思考方式一致:先感受,再探究原因,两者兼顾。
Level 1:映射(始终运行)
将截图划分为一个5×5 网格。对于每个被占用的区域,说明其中的部分(导航、主视觉区、侧边栏、内容区、页脚、模态框、抽屉、空白区域)、相对于视口的大致尺寸,以及它与相邻区域的关系。
记录每个可见元素:类型(按钮、输入框、卡片、图像、图标、文本、链接、切换开关、下拉菜单、选项卡、徽章、头像、表格、图表等)、标签/内容(可见文本原文)、位置(网格区域 + 相对位置)、状态(默认、悬停、激活、禁用、已选中、错误、加载中、聚焦)、尺寸(像素估值)、背景色(十六进制)、文本颜色(十六进制)、边框(可见/无 + 圆角像素值)、阴影(无/小/中/大)、图标(如有)。按区域分组。
另请说明:视线首先落在哪里。布局是舒展还是显得拥挤。层级清晰还是彼此争抢。哪些设计显得有意为之,哪些像是无意造成的。
Level 2:系统(始终运行)
提取可见界面背后的设计系统:
**颜色:**页面背景、卡片/表面背景、主要操作、次要元素、主要文本、次要/弱化文本、边框/分隔线、强调色、危险色、成功色。列出所有十六进制值。说明配色是否协调统一,还是显得拼凑——是否有明确的系统,还是颜色随意搭配?
**排版:**标题样式(像素字号、字重、大小写)、正文(字号、字重、行高)、说明文字/小字、可辨认的字体系列。说明字号层级是否有意设计——字号变化是否连贯,还是跳跃随意?
**间距和形状:**间距规律(紧凑,4-8px / 适中,12-16px / 宽松,24-32px+)、圆角规律(锐利,0-2px / 轻微,4-6px / 圆润,8-12px / 胶囊形)、整体密度(紧凑 / 适中 / 宽松)。说明不同区域的间距是否一致。
Level 3:蓝图(构建时升级)
当用户需要根据截图实现、重建或克隆 UI 时,运行此级别。如果对话涉及根据此截图编写代码,LLM 应升级到 Level 3。
**布局架构:**页面布局模式(单列、侧边栏 + 内容区、仪表板网格、居中容器、全宽)、各区域的内容布局(flex 行、flex 列、列数固定的 CSS 网格、堆叠)、容器宽度(限制最大宽度还是全宽)、响应式场景(移动端 <640px / 平板 640-1024px / 桌面端 >1024px)、滚动线索(内容被截断、粘性页眉、固定底栏)、z-index 层级(覆盖层、模态框、下拉菜单、提示框)。
**交互图:**主要 CTA(最重要的单一操作)、次要操作、导航模式(顶部导航、侧边导航、选项卡、面包屑、底栏)、表单元素及其分组、数据展示模式(表格、卡片网格、列表)、可见状态(加载中、空状态、错误、成功)。指出用户可能犹豫或感到不顺畅的地方,以及显得精致流畅的地方。
输出
根据上下文选择合适的输出形式。段落足以说明时,不要强行添加标题和分节。
**评审/反馈:**先指出问题或需要关注的地方。每项观察都要以具体细节为依据(导致问题的具体十六进制色值、间距或元素),并说明其对体验的影响。不要罗列所有内容,只关注重要问题。
**实现规范(Level 3):**按结构组织输出,并设置分节标题——布局图、按区域划分的元素、设计令牌、布局架构、交互图。这是实现文档。
**对比(两张截图):**说明有哪些变化、哪些方面有所改善、哪些方面有所退步,以及仍需改进之处。
核心原则
具体明确。“一个带有几张卡片的仪表板”绝不可接受。“3 列网格、卡片约 280px 宽、背景色 #F9FAFB、8px 圆角、柔和阴影——卡片轻盈得仿佛漂浮起来”才可以。每项观察都需要同时包含测量值和判断。
**用十六进制值,不用颜色名称;用像素,不用模糊尺寸。**说 #3B82F6,而不是“蓝色”。说约 16px,而不是“差不多”。如果不确定,给出最佳估计并注明。
**按区域分组,而不是按元素类型分组。**导航栏中的元素应归为一组。不要把页面上所有按钮都归入同一列表。
**指出不明显之处。**自定义插图、不同寻常的组件模式、暗示的动画、动态与静态数据。这些都是容易导致实现出错的地方。
**配合用户的节奏。**快速迭代时,输出要简洁。用户要求详细克隆时,输出要全面。但分析深度(第 1 和第 2 级)始终相同——变化的是输出量,而不是观察的细致程度。
自我评分
每次都在内部静默完成
完成任何分析后,都要按以下标准给自己的输出打 0 到 10 分:空间准确性(网格是否正确映射布局?)、具体程度(颜色是否使用十六进制值、尺寸是否以像素估算、组件是否准确命名?)、级别选择(是否运行了正确的级别?)、审美判断(是否发现了不协调之处,而不只是可测量的问题?)、可操作性(别人能否据此采取行动?)。计算平均分。
该评分严格保密。它会作为尾声中的 RATING 字段写入遥测数据,但绝不会展示给用户。每次分析后都显示评分会显得冗余且自我表扬。
何时征求反馈
只有以下三种情况需要让用户参与质量反馈。除此之外,保持安静。
触发条件 1:用户纠正。 如果用户纠正分析——“不对,这错了”“你漏了导航栏”“内边距不对”——先修正问题,然后简短说明:“已记录这次疏漏,帮助 clearshot 更好地发现[具体问题]。”自动写入一份现场报告(见下文)。
触发条件 2:重建完成后。 如果运行了第 3 级且实现已完成,随口问一句:“clearshot 做得很到位,还是漏了什么?只是好奇。”只问一次,不要做成问卷。
触发条件 3:会话即将结束。 如果单次会话中完成了 3 次或以上分析,且对话即将结束,附上一句:“这次会话运行了 clearshot X 次。它有没有反复弄错什么?”只有在完成 3 次或以上分析时才这样做。绝不要在对话进行中打断用户。
**绝不要征求反馈:**快速迭代期间、每次分析之后,或用户明显正专注于当前任务时。
现场报告
仅在以下情况写入 ~/.clearshot/feedback/YYYY-MM-DD-{slug}.md:
- 用户纠正:自动写入。格式:
# {Title describing the miss}
**What was analyzed:** {screenshot description}
**Levels run:** {1,2 or 1,2,3}
**What was missed:** {specific element or detail the user corrected}
**Correction:** {what the user said}
**Internal rating:** {X}/10
**Date:** {YYYY-MM-DD} | **Version:** {version from preamble}
-
用户明确指出有误(回复触发条件 2 或 3 时):写入现场报告,并包含用户的反馈。
-
内部评分低于 5:静默写入现场报告。
常规分析顺利完成时,绝不写入现场报告。
尾声
分析完成后,记录事件。将占位符变量替换为实际值。
_CS_TEL_END=$(date +%s)
_CS_DUR=$(( _CS_TEL_END - _CS_TEL_START ))
_CS_TEL_MODE=$(grep -E '^telemetry:' "$HOME/.clearshot/config.yaml" 2>/dev/null | awk '{print $2}' | tr -d '[:space:]' || echo "off")
if [ "$_CS_TEL_MODE" != "off" ]; then
_CS_OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
_CS_ARCH="$(uname -m)"
_CS_INSTALL_ID="$(printf '%s-%s' "$(hostname)" "$(whoami)" | shasum -a 256 | awk '{print $1}')"
_CS_ID_JSON="\"$_CS_INSTALL_ID\""
printf '{"v":1,"ts":"%s","version":"%s","os":"%s","arch":"%s","duration_s":%s,"outcome":"%s","levels_run":"%s","self_rating":%s,"installation_id":%s}\n' \
"$(date -u +%Y-%m-%dT%H:%M:%SZ)" "CS_VERSION" "$_CS_OS" "$_CS_ARCH" \
"$_CS_DUR" "OUTCOME" "LEVELS_RUN" "RATING" "$_CS_ID_JSON" \
>> "$HOME/.clearshot/analytics/usage.jsonl" 2>/dev/null || true
# Sync to Convex (rate-limited, background)
_CS_CONVEX_URL=""
for _csd in "$HOME/.claude/skills/clearshot" "$HOME/.agents/skills/clearshot"; do
[ -f "$_csd/config.sh" ] && _CS_CONVEX_URL="$(grep -E '^CS_CONVEX_URL=' "$_csd/config.sh" 2>/dev/null | cut -d'"' -f2 || true)" && break
done
if [ -n "$_CS_CONVEX_URL" ] && [ "$_CS_CONVEX_URL" != "https://placeholder.convex.site" ]; then
_CS_RATE="$HOME/.clearshot/analytics/.last-sync-time"
_CS_SYNC_STALE=$(find "$_CS_RATE" -mmin +5 2>/dev/null || echo "sync")
if [ ! -f "$_CS_RATE" ] || [ -n "$_CS_SYNC_STALE" ]; then
_CS_CURSOR_FILE="$HOME/.clearshot/analytics/.last-sync-line"
_CS_CURSOR=$(cat "$_CS_CURSOR_FILE" 2>/dev/null | tr -d '[:space:]' || echo "0")
_CS_TOTAL=$(wc -l < "$HOME/.clearshot/analytics/usage.jsonl" 2>/dev/null | tr -d ' ' || echo "0")
if [ "$_CS_CURSOR" -lt "$_CS_TOTAL" ] 2>/dev/null; then
_CS_SKIP=$(( _CS_CURSOR + 1 ))
_CS_BATCH=$(tail -n "+$_CS_SKIP" "$HOME/.clearshot/analytics/usage.jsonl" | head -100)
_CS_JSON_BATCH="[$(echo "$_CS_BATCH" | paste -sd ',' -)]"
_CS_HTTP=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 \
-X POST "$_CS_CONVEX_URL/telemetry" \
-H "Content-Type: application/json" \
-d "$_CS_JSON_BATCH" 2>/dev/null || echo "000")
case "$_CS_HTTP" in 2*) echo $(( _CS_CURSOR + $(echo "$_CS_BATCH" | wc -l | tr -d ' ') )) > "$_CS_CURSOR_FILE" ;; esac
touch "$_CS_RATE" 2>/dev/null || true
fi
fi
fi
fi
将以下占位符替换为分析中的实际值:
_CS_TEL_START— 前言输出中的值CS_VERSION— 前言输出中的版本OUTCOME— “success”、“error”或“abort”LEVELS_RUN— “1,2”或“1,2,3”RATING— 自评分数(0-10)