- 后端
- 前端
- 社交
- 人工智能
【免费下载链接】NewsBlur
NewsBlur is a personal news reader that brings people together to talk about the world. A new sound of an old instrument.
导读
feature.md是 NewsBlur 仓库中为 Claude Code 定制的一条斜杠命令(slash command),它把「发布新功能公告」这件事做成了可复用的 Agent 工作流:自动检索匹配的博客文章、按既有风格生成多个功能描述候选、经用户确认后直接写入生产数据库的 Features Board,并附带 3 至 5 组现成推文。本文结合仓库源码拆解该命令的完整设计:从命令的 frontmatter 声明、上下文注入,到七步执行流程,再到Feature模型的底层实现、权限控制与 Features Board 的前端渲染,让你既能照搬这套发布流程,也能理解它背后的数据链路。
一、命令定位:.claude/commands/feature.md是什么
在 NewsBlur 仓库的.claude/commands/目录下,存放着一批面向 AI 编码助手(Claude Code)的自定义命令,feature.md是其中之一,专门负责「向生产环境的 Features Board 发布一条新功能,并撰写配套推文」。
命令文件采用标准的 YAML frontmatter 声明元信息:
--- description: Post a feature to the Features Board on production and write tweets allowed-tools: Bash, Read, Glob, Grep, AskUserQuestion ---description:描述命令用途,供 Agent 理解何时该调用这条命令;allowed-tools:白名单限定本次任务只允许使用 Bash(执行命令)、Read(读文件)、Glob(文件匹配)、Grep(搜索)和 AskUserQuestion(向用户提问)五类工具,其余能力被显式禁用。
同目录还包含blog-post.md、commit.md、worktree.md等命令,可见该项目把常见的「写博客、提 commit、发布功能」等维护动作全部脚本化成了 Agent 可执行的命令,feature.md就是其中连接「博客内容」与「产品公告」的环节。
二、上下文注入:让 Agent 先「看清现场」
命令正文的开头是 Context(上下文)部分,包含两条动态指令,要求 Agent 在动手前先收集两类现场信息:
# 1. 最近发布的博客文章 !`ls -t blog/_posts/*.md | head -10` # 2. 生产环境当前已上线的功能列表 !`./utils/ssh_hz.sh -n happ-web-01 "docker exec -t newsblur_web python manage.py shell -c \"from apps.reader.models import Feature; [print(f'{f.date.strftime(\\\"%b %d, %Y\\\")}: {f.description}') for f in Feature.objects.all()[:6]]\""`这两条指令一前一后形成了任务的参照系:
- 第一条用
ls -t按修改时间倒序列出blog/_posts/下最近 10 篇博客文章,用于后续「找一篇与功能主题匹配的文章」; - 第二条则是真实的运维链路:通过 utils/ssh_hz.sh 登录到生产应用机(别名
happ-web-01),在newsblur_web容器内用 Django shell 查询apps.reader.models.Feature表最近 6 条记录,作为风格模板。
仓库中blog/_posts/目录确实按YYYY-MM-DD-slug.md命名,例如2026-03-25-daily-briefing.md、2026-04-06-premium-pro.md,与命令中推导博客 URL 的规则完全对应。
ssh_hz.sh如何工作
utils/ssh_hz.sh 是整条链路的关键基础设施。它从ansible/inventories/hetzner.ini中按别名解析主机 IP,再以固定密钥发起 SSH:
- 支持
-n|--noninteractive非交互模式,-n后的第一个参数是服务器别名,其余参数全部作为远程命令透传; - 别名解析逻辑:先在 ini 中做整行精确匹配(
grep "^$1[[:space:]]"),失败则回退到子串匹配,同时跳过以;或#开头的注释行; - 连接参数固定为
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /srv/secrets-newsblur/keys/docker.key,登录用户为nb@$HOST; - 在仓库中,
ansible/inventories/hetzner.ini是一个指向/srv/secrets-newsblur/configs/hetzner.ini的符号链接,实际主机清单存于保密目录;而 ansible/inventories/hetzner.yml 定义了主机分组逻辑,happ-web-01属于django/hdjango组(以happ-web开头),即承载 Django Web 服务的生产实例。
也就是说,这条 Context 指令是经过真实生产环境验证的写法:SSH 进 Django 容器、用manage.py shell -c执行单行查询,全程无人值守。
三、写作风格:拒绝「AI 味」
命令用一节专门约束所有产出的文风(功能描述与推文都要像人写的):
- 不使用 em dash 或双连字符,甚至「不用破折号做标点」,而是重组句子;
- 不要过度打磨、不要企业腔,保持直接、自然;
- 不要套话,例如 "excited to announce"、"we're thrilled"、"game-changer" 这类空泛短语;
- 写作基调:像开发者向用户介绍自己的产品一样朴实。
这节是命令的灵魂:Features Board 和推文都是面向真实用户的内容,一旦写得像模板生成的营销文案,功能公告的可信度与可读性都会下降。
四、七步执行流程
命令将整个任务拆成 7 个明确步骤,每一步都有可验证的产出物。
Step 1:定位匹配的博客文章
在blog/_posts/中搜索与主题(命令参数{{ arguments }})匹配的博文并通读全文,重点提取:
- 功能做什么;
- 关键能力与亮点;
- 哪些订阅套餐(tier)可使用;
- 博文日期与 URL slug。
博客 URL 由文件名推导,规则为https://blog.newsblur.com/YYYY/MM/DD/slug-from-filename/,例如blog/_posts/2026-03-25-daily-briefing.md对应https://blog.newsblur.com/2026/03/25/daily-briefing/。这条规则与仓库中博客文件的命名习惯(如2026-04-01-mcp-server-and-cli.md、2026-07-17-good-reads-and-a-redesigned-global-shared-stories.md)一一对应。
Step 2:研究现有功能的风格基线
以 Context 部分取回的 6 条生产记录为样本,归纳出 Features Board 条目的格式规范:
- 长度:1 至 3 句,精炼有力;
- 语气:产品导向,突出「新在哪、有什么用」;
- 结构:功能描述正文 +
<a href="...">Read the blog post</a>; - 内容:先讲功能做什么,再压缩关键细节,偶尔提及套餐可用性;
- 字段性质:
description字段存放的是原始 HTML,博客链接是其中的<a>锚点标签。
这一点在源码中能得到印证:templates/reader/features_module.xhtml 直接以{{ feature.description|typogrify }}渲染该字段,说明描述内嵌 HTML 是设计使然,前端会原样输出。
Step 3:产出 4 至 5 个候选描述
在既有风格内做多角度变体,差异点包括:突出功能的广度还是深度、长度(短 vs 略长)、纳入哪些细节(分节、投递方式、自定义选项、套餐信息)。所有候选以纯文本形式呈现在对话中,避免使用 AskUserQuestion 的预览框(预览会截断 HTML)。
Step 4:让用户拍板
用 AskUserQuestion 单选(不带预览)让用户选择,选项标签要能体现每个候选的角度差异(例如 "Balanced, both features" 或 "Problem-first framing")。
Step 5:写入生产数据库(核心命令)
用户选定后,通过以下命令在happ-web-01的生产环境创建 Feature 记录:
./utils/ssh_hz.sh -n happ-web-01 "docker exec -t newsblur_web python manage.py shell -c \" from apps.reader.models import Feature import datetime f = Feature( description='<THE CHOSEN DESCRIPTION WITH HTML LINK>', date=datetime.datetime.utcnow() + datetime.timedelta(minutes=1) ) f.save() print(f'Created Feature #{f.id}: {f}') \""这条命令的要点:
- 通过
ssh_hz.sh直达生产机,再docker exec进入newsblur_web容器; - 直接以 ORM 方式构造
Feature对象并save(),不经过任何 HTTP 接口; - 日期刻意设为「当前 UTC 时间 + 1 分钟」,避免因时钟偏差导致记录时间戳早于当前时刻;
- 命令结束后打印
Feature #<id>用于回执。
命令末尾特别强调:嵌套 shell 命令中必须正确转义描述内容里的引号。因为描述字段含 HTML 锚点(本身就有引号),而整段代码又经过 bash → ssh → docker exec → python shell 四级嵌套,引号层级稍有错乱就会导致命令中断或字段截断。
Step 6:确认上线
向用户回报生成的 Feature ID,并确认该条目已在生产环境生效。
Step 7:撰写推文集
产出 3 至 5 组推文(每组 2 至 3 条,可作为一条 Thread 或独立发布),每条的硬性要求:
- 长度在 280 字符以内(URL 不计入,Twitter 会自动缩短);
- 以博客 URL 独占一行结尾;
- 遵守上文写作风格(不用破折号、不写 AI 套话)。
各组从不同角度切入:有的同时覆盖两个功能、有的聚焦单一功能、有的给出具体示例、有的短小精悍。推文候选直接在对话中以纯文本、编号形式展示,方便用户直接复制,不再走 AskUserQuestion(与 Step 4 刻意形成差异化交互)。
五、底层支撑:Features Board 的数据链路
feature.md命令写入的其实是 NewsBlur 首页 Dashboard 上的一块「类博客功能公告板」,它的完整数据链路如下:
1. 模型层
apps/reader/models.py 第 3196 至 3208 行定义了极简的Feature模型:
class Feature(models.Model): """ Simple blog-like feature board shown to all users on the home page. """ description = models.TextField(default="") date = models.DateTimeField(default=datetime.datetime.now) def __str__(self): return "[%s] %s" % (self.date, self.description[:50]) class Meta: ordering = ["-date"]description:公告正文(含 HTML 博客链接);date:发布时间,模型默认datetime.datetime.now(命令则显式改为 UTC 时间并加 1 分钟);Meta.ordering = ["-date"]:查询结果默认按日期倒序,最新公告排在最前。
配套测试工厂 apps/reader/factories.py 中的FeatureFactory用 Faker 生成description与date,方便在测试环境复现公告数据。
2. 表单层
apps/reader/forms.py 的FeatureForm复刻了命令的日期逻辑:
class FeatureForm(forms.Form): use_required_attribute = False description = forms.CharField(required=True) def save(self): feature = Feature( description=self.cleaned_data["description"], date=datetime.datetime.utcnow() + datetime.timedelta(minutes=1), ) feature.save() return feature可见「utcnow + 1 分钟」并非命令独有,而是 Web 端新增公告(Dashboard 上的 Add Feature 表单)与 CLI 命令共用的同一套约定。
3. 视图层与权限
apps/reader/views.py 有两个相关视图:
add_feature(第 4602 至 4615 行):处理 Web 表单提交,以request.user.is_staff校验管理员权限,非 staff 直接返回HttpResponseForbidden()。生产运维走命令行的原因也与此一致:命令行方式天然绕过了 Web 表单,需要操作者掌握 SSH 与容器权限;load_features(第 4618 至 4632 行):对外提供 JSON 接口,按[page * 3 : (page + 1) * 3 + 1]分页,即每页取 4 条(其中第 4 条用于判断是否还有下一页),并把日期按用户时区格式化为"%b %d, %Y"。
两条路由注册在 apps/reader/urls.py:^add_feature(name 为add-feature)与^features(name 为load-features)。
4. 展示层
templates/reader/features_module.xhtml 渲染公告板表格:
{% for feature in features %} <tr class="NB-module-feature {% if forloop.last %}last{% endif %} {% if feature.date > user.profile.last_seen_on %}NB-module-feature-new{% endif %}"> <td class="NB-module-feature-date">{% localdatetime feature.date "%b %d, %Y" %}</td> <td class="NB-module-feature-description">{{ feature.description|typogrify }}</td>- 日期以本地化格式显示;
- 描述经
typogrify过滤器做排版优化(正确处理智能标点等); - 若公告日期晚于用户上次访问时间(
user.profile.last_seen_on),自动加NB-module-feature-new类做「新公告」视觉高亮。
该模块被嵌入首页仪表盘 templates/reader/dashboard.xhtml,并配合一段 JS($('#add-feature-button').click(...))控制「Add」表单的显隐。也就是说,用户在首页看到的每一条功能公告,都对应着Feature表里的一行记录,而这正是feature.md命令直接操作的对象。
六、实战要点与注意事项
把feature.md的工作流搬到自己的发布流程中时,有几处细节值得留意:
- 引号转义是最大的坑:描述中的 HTML 链接(
<a href="...">)带双引号,整条命令要穿透 bash、ssh、docker exec、python shell 四层解释器,建议先在本地用单层python -c验证描述字符串,再套进完整命令。 - 时间戳策略:
date使用utcnow + timedelta(minutes=1),既保证记录出现在「现在」之后,又能容忍一定时钟偏差;前端正是依据这个时间戳做「新功能」高亮。 - 权限边界:Web 端的
add_feature视图受is_staff保护;命令行发布依赖ssh_hz.sh的密钥(/srv/secrets-newsblur/keys/docker.key)与容器访问权,两条路径的权限模型不同,生产操作前应确认具备对应凭据。 - 风格一致性:Features Board 与推文都面向真实用户,命令用「长度 1 至 3 句、产品导向、含博客链接、避免 AI 套话」四条基线约束全部产出,保证任何 Agent 生成的内容都与历史公告同源同质。
- 可回滚与可验证:
save()后打印Feature #<id>作为回执;也可以随时用 Context 中的查询命令复核最新 6 条记录,确认公告已生效。
七、总结
feature.md完整展示了 NewsBlur 团队如何把「内容运营」也纳入自动化:它一端连接blog/_posts/的写作产出,一端连接生产库Feature表的写入,中间用「风格基线 + 用户确认 + 多角度候选」三件套保证输出质量。理解这条命令,不仅能用它发布公告,更能看到 NewsBlur 首页 Features Board 从模型、表单、视图到模板的完整实现链路。如果你也在维护一个带公告板或 Changelog 的产品,这套「命令定义 + 动态上下文 + 生产直写」的范式值得直接借鉴。
- 后端
- 前端
- 社交
- 人工智能
【免费下载链接】NewsBlur
NewsBlur is a personal news reader that brings people together to talk about the world. A new sound of an old instrument.
相关推荐
NewsBlur 仓库的智能提交与推送:基于 Claude Code 的 commit-push 工作流解析
NewsBlur 仓库的智能提交与推送:基于 Claude Code 的 commit push 工作流解析 导读 在 NewsBlur 这类大型开源仓库中,A
后端前端社交人工智能ruflo release-manager:用 Claude Code 命令构建 Swarm 协同的多包发布流水线
ruflo release manager:用 Claude Code 命令构建 Swarm 协同的多包发布流水线 本文以 ruflo(claude flow)
人工智能AI Agent多智能体Agent 编排Agent 记忆工具调用代码智能体MCP 服务AI 评测使用 Claude Code `/prp-mcp-execute` 命令:从 PRP 到生产级 MCP 服务器的可执行工作流
使用 Claude Code /prp mcp execute 命令:从 PRP 到生产级 MCP 服务器的可执行工作流 导读 /prp mcp execute
文档教程提示工程人工智能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考