关于 pp-table-reservation-goat
pp-table-reservation-goat 是用于操作 CLI 的技能,可跨 OpenTable、Tock 和 Resy 搜索餐厅与预订信息。它支持查询空位和管理预订,并为 Agent 工作流在本地保存学习记录与查询数据。
主要功能
- 01跨三个平台搜索餐厅
- 02查询单日和多日空位
- 03列出、预订、修改和取消预约
- 04读取收藏餐厅和用户资料
- 05在本地保存查询与学习数据
- 06以 Agent 模式输出结构化结果
适用场景
- 01跨平台比较餐厅空位
- 02查询数日内的可订时段
- 03预订或取消餐位
- 04复用本地保存的餐厅查询经验
MCP 相关
README 介绍了 table-reservation-goat MCP 服务,并提供在 MCP 主机中配置的示例。可通过环境变量迁移该服务保存的数据和凭据。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mvanhorn/ printing-press-library --skill pp-table-reservation-goat安装后在 Claude Code 中输入/pp-table-reservation-goat确认已加载。
详细介绍
Table Reservation Goat — Printing Press CLI
前提条件:安装 CLI
此技能使用 table-reservation-goat-pp-cli 二进制文件。调用此技能中的任何命令前,必须确认 CLI 已安装。 如果尚未安装,请先安装:
- 使用 Printing Press 安装程序安装。在 macOS/Linux 上,二进制文件默认安装到
$HOME/.local/bin;在 Windows 上,默认安装到%LOCALAPPDATA%\Programs\PrintingPress\bin:npx -y @mvanhorn/printing-press-library install table-reservation-goat --cli-only - 验证:
table-reservation-goat-pp-cli --version - 确保报告的安装目录已添加到将调用此技能的 Agent/运行时的
$PATH中。
如果 npx 安装失败(没有 Node、处于离线状态等),请改用直接通过 Go 安装(需要 Go 1.26.6 或更高版本)。该方式会将程序安装到 $GOPATH/bin(默认是 $HOME/go/bin),因此请改为将此目录添加到 $PATH 中:
go install github.com/mvanhorn/printing-press-library/library/food-and-dining/table-reservation-goat/cmd/table-reservation-goat-pp-cli@latest
如果安装后 --version 报告“command not found”,则运行时无法在 $PATH 中找到二进制文件目录。验证成功前,请勿执行此技能中的命令。
一个适用于 OpenTable、Tock 和 Resy 的预订 CLI——同时搜索这三个网络、监控取消情况、端到端完成预订和取消,并跟踪变更,数据存储在 Agent 可查询的本地存储中。
命令参考
availability — 查询 OpenTable、Tock 和 Resy 上的空余预订时段
table-reservation-goat-pp-cli availability check— 查询指定餐厅在特定日期和用餐人数下的空余时段table-reservation-goat-pp-cli availability multi-day— 查询单家餐厅多日的空余情况——周一至周日矩阵
experiences — 列出预付费和品鉴菜单体验(Tock 风格)
me — 从两个网络读取已认证的用户个人资料
reservations — 列出、预订、修改和取消预订(需要登录认证)
仅当显式配置了 TABLE_RESERVATION_GOAT_OT_CHROME_DEBUG_URL,且已附加的配置文件已登录时,才会启用 OpenTable 附加式预订。使用 TRG_ALLOW_BOOK=prepare 可执行至已启用的最终确认控件,但不会点击;只有 TRG_ALLOW_BOOK=1 才能提交预订。类型化失败包括 attach_unreachable、not_signed_in、selector_drift、form_validation、slot_taken 和 incomplete_confirmation;page_state 诊断信息会经过脱敏处理,绝不会包含 URL 查询令牌或任意账户标签。
Tock 预订优先使用 TABLE_RESERVATION_GOAT_TOCK_CHROME_DEBUG_URL 指定的已登录 Chrome 会话(默认值为 http://localhost:9222),并保留隐身无头会话回退方式。它会先尝试旧版时段按钮,然后尝试精确时间的 /search 行,以及新版时间组合框/体验卡片控件。Agent 和 --no-input 运行不会提示输入 CVC:仅在需要时提供 3 位或 4 位的 TRG_TOCK_CVC。类型化失败包括 cvc_required 和 selector_drift;选择器诊断信息仅包含不带查询参数的路径、布尔值、时间标签和允许列表中的控件类别。
restaurants — 搜索并查看 OpenTable、Tock 和 Resy 上的餐厅
table-reservation-goat-pp-cli restaurants get— 获取餐厅的完整详情——营业时间、地址、菜系、价格区间、照片、荣誉table-reservation-goat-pp-cli restaurants list— 列出 OpenTable、Tock 和 Resy 上的餐厅;可按位置、菜系、价格区间、荣誉和用餐人数筛选
wishlist — 从两个网络读取你已保存/加入愿望清单的餐厅
查找合适的命令
当你知道要做什么,却不知道该用哪个命令时,可以直接向 CLI 提问:
table-reservation-goat-pp-cli which "<capability in your own words>"
which 会根据自然语言功能查询,从此 CLI 精选的功能索引中找出最匹配的命令。退出代码 0 表示至少有一个匹配项;退出代码 2 表示没有足够可信的匹配项——请改用 --help 或缩小查询范围。
身份验证设置
搜索和可用性查询无需账户。OpenTable 和 Tock 的附加预订使用已登录的 Chrome 配置文件会话;Tock 保留已保存会话的隐身无头模式回退方案;Resy 预订使用其已保存的 API 令牌。
运行 table-reservation-goat-pp-cli doctor 验证设置。
Agent 模式
在任何命令中添加 --agent。它会展开为:--json --compact --no-input --no-color --yes。
-
可管道传输 — JSON 输出到 stdout,错误输出到 stderr
-
可筛选 —
--select保留字段子集。点分路径可深入嵌套结构;数组会逐元素遍历。对于内容冗长的 API,这对控制上下文大小至关重要: -
可预览 —
--dry-run显示请求但不发送 -
离线友好 — 有本地 SQLite 存储时,同步/搜索命令可使用该存储
-
非交互式 — 从不提示输入,所有输入均通过标志传入
-
显式重试 — 仅当已存在的创建操作应视为成功时才使用
--idempotent;仅当缺失的删除目标应视为成功时才使用--ignore-missing
响应封装
从本地存储或 API 读取数据的命令,会将输出包装在来源封装中:
{
"meta": {"source": "live" | "local", "synced_at": "...", "reason": "..."},
"results": <data>
}
解析 .results 获取数据,并查看 .meta.source 判断数据来自实时来源还是本地存储。只有当 stdout 是终端且未设置机器格式标志(--json、--csv、--compact、--quiet、--plain、--select)时,才会将易读的 N results (live) 摘要打印到 stderr;管道/Agent 使用者以及显式格式运行都会在 stdout 上获得纯 JSON。
路径和状态
Agent 应将 CLI 的路径解析器视为运行时约定的一部分:
-
使用
--home <dir>设置单次调用的路径,或设置TABLE_RESERVATION_GOAT_HOME=<dir>,将所有四类路径重定位到同一个根目录下。 -
仅当某一特定类型的路径需要单独指定时,才使用对应类型的环境变量:
TABLE_RESERVATION_GOAT_CONFIG_DIR、TABLE_RESERVATION_GOAT_DATA_DIR、TABLE_RESERVATION_GOAT_STATE_DIR、TABLE_RESERVATION_GOAT_CACHE_DIR。 -
解析顺序为:对应类型的环境变量、
--home、TABLE_RESERVATION_GOAT_HOME、XDG(XDG_CONFIG_HOME、XDG_DATA_HOME、XDG_STATE_HOME、XDG_CACHE_HOME),然后是平台默认值。 -
config包含config.toml和配置档案等设置。data包含credentials.toml、data.db、Cookie 和身份验证旁文件。state包含持久化查询、作业和teach.log。cache包含可重新生成的 HTTP/缓存文件。 -
已存储的密钥位于 data 目录下的
credentials.toml中。为兼容性,仍会读取现有旧版config.toml中的密钥,并在首次身份验证写入时将其移出config.toml。 -
运行
table-reservation-goat-pp-cli doctor --fail-on warn以显示路径和凭据位置警告。对于需要解析后目录路径的 Agent,agent-context会提供 schema v4 的paths块。 -
对于 MCP,请通过 MCP 主机配置传入重定位设置。MCP 二进制文件不会继承 CLI 标志:
{ "mcpServers": { "table-reservation-goat": { "command": "table-reservation-goat-pp-mcp", "env": { "TABLE_RESERVATION_GOAT_HOME": "/srv/table-reservation-goat" } } } }
集群优先级:继承的对应类型环境变量会覆盖该类型的显式 --home。使用 TABLE_RESERVATION_GOAT_HOME 或对应类型的变量作为持久的集群控制项;--home 仅用于单次调用。重定位无法通过取消设置环境变量来撤销;清除 TABLE_RESERVATION_GOAT_HOME 前,请手动移动文件,否则 doctor 将无法找到留在原根目录下的凭据。
自动学习
此 CLI 内置自动捕获的学习循环。CLI 会自行记录:每次调用都会记入本地日志;标志失败后经修正重试时,会自动推导出一个 flag_alias 候选项;对于没有操作手册的查询类别执行 teach 时,会根据会话日志自动合成一个 playbook_candidate。你只需负责判断:先执行 recall,再处理显示的候选项,执行 teach 记录最终答案,并在发现更正时执行 playbook amend。你无需手动记录失败。
步骤 1:任何发现操作前先运行 recall
针对新的用户问题,在运行 list/search/drill 命令前,先运行:
table-reservation-goat-pp-cli recall "<user's question>" --agent
响应封装:
{
"query": "...",
"normalized": "<normalized form>",
"query_entities": ["..."],
"found": true | false,
"match_score": 0.0,
"results": [
{ "resource_id": "...", "resource_type": "...", "venue": "...",
"confidence": 2, "entity_match": "exact|partial|unknown",
"source": "taught|preseed|pattern", "warnings": ["..."] }
],
"mismatches": [ /* only when --debug-mismatches */ ],
"warnings": [ /* top-level */ ],
"candidates": [
{ "id": 12, "class": "flag_alias | playbook_candidate",
"summary": "...", "sightings": 3, "last_seen": "...",
"rationale": "...",
"next_action": ["<trial command>", "table-reservation-goat-pp-cli learnings confirm 12"] }
],
"playbook": {
"query_family": "...",
"playbook": {
"steps": [ { "cmd": "<command with {slot} substitution>", "purpose": "..." } ],
"entity_slots": ["$ENTITY"],
"expected_tool_calls": 3
},
"slots_resolved": { "$ENTITY": { "token": "<live token>", "canonical": "<canonical>" } },
"notes": "<workarounds + gotchas for this query family>"
},
"notes": "<duplicate surface for non-playbook callers>"
}
空存储时短路:如果存储中尚无学习项、操作手册或候选项(recall 没有结果,且 learnings list 和 learnings candidates 均为空),则本次会话剩余时间内跳过 recall,避免每次查询都付出代价;教入新内容后,再恢复优先运行 recall。
步骤 2:决策树
按以下顺序读取 candidates、playbook、notes、results[0] 和 warnings:
if Candidates present (warnings include "candidates_present"):
-> candidates are try-then-confirm, never facts. Follow each candidate's
two-step next_action verbatim: run the trial command first, then run
`learnings confirm <id>` only after the trial verified the behavior.
Reject a wrong candidate with `learnings reject <id>`.
-> NEVER re-teach something recall surfaced as a candidate; confirm or
reject that candidate instead of teaching a duplicate.
-> candidates ride alongside playbooks and resource hits, not instead of
them; continue with the branches below after acting on them.
if Playbook present:
-> READ Playbook.notes verbatim FIRST (workarounds + gotchas the CLI surface doesn't expose)
-> replay Playbook.steps in order, substituting Playbook.slots_resolved entries
for the entity slot tokens. If a step's slot is unresolved, fall back to
discovery for that step only.
-> the Playbook's expected_tool_calls is a budget; if you find yourself running
materially more, record the divergence via `table-reservation-goat-pp-cli playbook amend`
at end-of-session.
elif Notes present (no Playbook):
-> read Notes verbatim before any discovery step; they carry known gotchas
for this query family even when no structured choreography exists yet.
elif Found AND Results[0].EntityMatch == "exact" AND Results[0].Confidence >= 2:
-> skip discovery; fetch live data for Results[*].ResourceID in parallel
elif Found AND Results[0].EntityMatch == "partial":
-> candidate hint, NOT a hit; read the resource title to validate before trusting
elif (any row in Mismatches[] when --debug-mismatches was passed):
-> treat as cold start; the stored learning is for a different entity
(different canonical resolved from query_entities)
else: // Found == false, no playbook, no notes
-> cold start; run discovery normally; teach the answer afterward (Step 4).
If the family has no playbook yet, that teach auto-synthesizes a
playbook candidate from this session's journal - you do not need to
record one by hand.
操作手册和备注与逐资源路径相互独立。recall 响应可以同时包含操作手册和 Results[] 命中项——两者都要使用:操作手册会告诉你要执行哪套流程;资源命中项则会让特定步骤提前结束。默认跳过 mismatches;仅在调查冷启动时出现的意外情况时传入 --debug-mismatches。
候选项判断详情:learnings confirm <id> 会在将候选项写入存储前打印其完整负载——请检查打印的负载是否与已验证的行为一致。learnings reject <id> 会将派生签名标记为已删除,避免同一候选项再次出现。封装中只包含当前值得采取行动的少数候选项;table-reservation-goat-pp-cli learnings candidates 会列出所有未处理项。
优雅降级:如果 learnings confirm 是未知命令,说明你使用的是旧版二进制文件——忽略候选项相关指引,并遵循协议的其余部分。
步骤 3:始终读取 warnings
low_confidence:confidence<2的行已存在。将其视为提示,而不是跳过发现流程的命中项。resource_not_in_store:本地存储中没有该学习项所指向的资源。匹配验证器无法对实体分类——直接获取资源并重新评估。cross_alias_match(每条结果):该行是在不同别名下教入的,并通过entity_lookups与实时查询的规范实体匹配(例如,以“USA”教入的内容满足了“United States”的召回请求)。请信任resource_id。similar_shape_different_entity:<canonical>(顶层):存在结构匹配的行,但其规范实体与实时查询的不同。按冷启动处理;warning 会将冲突的规范实体作为提示,但该行不会提升为 Results。ambiguous_alias(顶层):单个查询实体解析到了多个规范实体(例如,“Cards” → Arizona Cardinals + St. Louis Cardinals)。在确定资源前,根据上下文指出这一歧义。candidates_present(顶层):封装中包含candidates部分。先按步骤 2 中的候选项分支处理,再进行其他操作。lookup_refresh_available(顶层):查询中的某个实体尚无查找行,但同步数据可能提供该行。运行table-reservation-goat-pp-cli sync以刷新实体查找数据。- 顶层
no_learnings_for_query_family:该表中没有 Jaccard 分数高于下限的行。属于纯冷启动。
第 4 步:完成回复后始终执行 teach &
教学是无条件的。解决存储无法回答的查询后,在后台教学最终资源映射——不设调用次数门槛,也不判断是否「值得」学习。教学是循环的锚点:对于尚无操作手册的类别,它会触发操作手册综合;同一指代对象的不同表述会归并到同一类别,因此近乎重复的教学不会让存储碎片化。组装好面向用户的回复后、发出回复前,使用 shell & 执行教学,让调用立即返回:
table-reservation-goat-pp-cli teach --query "<user's question>" --resource-type <type> --resource <id1> --resource <id2>
# (append shell `&` to background it)
成功时保持静默。错误只会写入已解析状态目录下的 teach.log。教学时选择最具体的资源——如果用户提出了宽泛的问题,而你通过查看上级记录找到了具体答案,就教学叶子 id,而不是上级记录。CLI 使用预置的 entity_lookups 在回忆时进行跨别名解析,因此以一个别名(例如「Niners」)进行教学后,未来使用其他别名(例如「49ers」、「San Francisco」)的查询也会自动得到满足。
PII 规则:教学时应保留结构性问题并剥除标识符——绝不要在教学查询或备注中包含姓名、电子邮件、电话号码、账户 id 或其他个人标识符。CLI 会扫描教学查询中的明显电子邮件/电话号码格式并发出警告,但不会阻止;教学前应先剥除这些信息,而不要依赖警告。
第 5 步:操作手册——可选标志,自动综合
你不需要判断某次会话是否「值得」编写操作手册:对于尚无操作手册的类别,教学会根据会话日志自动综合出一个 playbook_candidate,并由下一次会话通过确认/拒绝来评判。仅当你已经掌握值得原样记录的操作流程时,才附加明确的操作手册标志——例如 CLI 未显示的变通方法(被静默丢弃的标志、未记录的参数、分页技巧、负载注意事项)。优先使用集成式单次调用形式——在同一个 teach 调用中记录资源学习和操作手册:
# Common case: record both the resource learning AND the playbook in one call.
table-reservation-goat-pp-cli teach \
--query "<user's question>" \
--resource <id> \
--playbook-file ~/playbooks/<shape>.json \
--playbook-notes-file ~/playbooks/<shape>-notes.md
# (append shell `&` to background it)
# Alternate: playbook-only (no resource to record alongside).
table-reservation-goat-pp-cli teach-playbook \
--query "<user's question>" \
--playbook-file ~/playbooks/<shape>.json \
--notes-file ~/playbooks/<shape>-notes.md
操作手册文件是包含 steps、entity_slots、expected_tool_calls 的 JSON 文件。备注文件是原样记录注意事项的 Markdown 文件。不使用文件的调用方(仅使用 MCP 的 Agent)可内联传入相同内容:在集成式 teach 形式中使用 --playbook-json 和 --playbook-notes,在 teach-playbook 形式中使用 --playbook-json 和 --notes。在集成式 teach 形式中,操作手册标志是可选的——若只进行资源教学,则完全省略这些标志。在独立的 teach-playbook 形式中,必须至少设置操作手册标志和备注标志中的一个;两者都为空时会被拒绝。操作手册按结构性查询类别(剥除实体后)建立索引,因此,从一个带实体的查询中教授的流程适用于所有其他同结构的查询;回忆时,slots_resolved 会绑定当前查询的规范值。
未来回忆时,只要找到操作手册,就应将其视为真实依据:使用 slots_resolved 替换值,重放各步骤,跳过操作流程中已有记录的探索过程,并在执行任何步骤前阅读 notes。
第 6 步:当调试响应指出需要更正时,执行 playbook amend &
如果你的调试协议响应指出了笔记或 playbook 应当了解的具体更正——例如变通方法、未记录的端点结构、过时的字段名称、观察到的架构漂移、空载荷回退方案——请在输出面向用户的响应之前执行 playbook amend。与 teach 一样,采用触发后即不等待的方式。
table-reservation-goat-pp-cli playbook amend \
--query "<exact recall query string>" \
--add-note "<your concrete correction>"
# (append shell `&` to background it)
哪些内容值得补充:你在本次会话中观察到、未来的你会从中受益的行为。值得补充的示例:
- CLI 界面会静默丢弃或打乱某个标志的变通方法。
- 未记录的端点结构(响应包装在
{meta, results}中,载荷嵌套的层级比文档所述多两层)。 - 观察到的架构漂移(字段重命名、索引在不同赛季间发生变化、API 现在返回小写类别标签)。
哪些内容不应写入笔记:
- 用户问题中与年份或实体相关的答案。这是响应内容,不是经验总结。
- playbook 已在运行时检索的各团队、各运动员或各行数据。
- 转述现有笔记内容的陈述。
amend 命令会在该系列现有笔记末尾追加带时间戳的标记([amend YYYY-MM-DDTHH:MMZ]: <text>)。多条 amend 会累积保存;审计记录清晰可见。如果该系列还没有 playbook,amend 会创建一个仅含笔记的 playbook(因此冷启动时的更正也能记录下来)。
amend 笔记中的 PII 规范
playbook amend 笔记未来可能会作为共享知识流向 Printing Press 的后续版本。请勿在笔记中包含可识别用户身份的内容,以便在无需事后清理的情况下保留向上游贡献的可能性:
- 请勿嵌入用户文件系统路径、个人 API 密钥或令牌、用户电子邮件地址、用户 GitHub 用户名,或与单个用户相关的特定查询历史。
- 可接受的内容:端点结构、未记录的字段名称、API 注意事项、观察到的架构漂移、CLI 界面的变通方法、可泛化的分页或重试技巧。
如果某项更正只有结合用户特定上下文才有意义,应将其记入个人笔记,而不是 playbook amend。
衡量循环效果
table-reservation-goat-pp-cli learnings stats 会根据本地 learn_events 表报告召回命中率、教学复用率、playbook 解析率,以及候选项确认/拒绝次数。尚无分母时,相关比率为 null;所有数据都保留在本机。使用它来检查该循环是否为此 CLI 带来了实际价值。
禁用学习
- 在单条命令上使用
--no-learn,会同时跳过recall和teach写入路径。可用于确定性 Agent 工作流,或不得受累积经验影响的测试。 - 在环境中设置
TABLE_RESERVATION_GOAT_NO_LEARN=true,可全局禁用该管线。
Agent 反馈
当你(或 Agent)注意到此 CLI 有异常之处时,请记录下来:
table-reservation-goat-pp-cli feedback "the --since flag is inclusive but docs say exclusive"
table-reservation-goat-pp-cli feedback --stdin < notes.txt
table-reservation-goat-pp-cli feedback list --json --limit 10
条目会以 feedback.jsonl 的形式存储在解析后的数据目录中。只有在设置了 TABLE_RESERVATION_GOAT_FEEDBACK_ENDPOINT,并且传入了 --send 或设置了 TABLE_RESERVATION_GOAT_FEEDBACK_AUTO_SEND=true 时,条目才会通过 POST 发送。默认情况下,数据仅保留在本地。
记录让你感到意外的事情,而不是提交错误报告。简短、具体、一行即可:这才是会不断累积价值的内容。
输出交付
每条命令都接受 --deliver <sink>。输出会发送到指定的接收端,同时也会输出到 stdout,或替代 stdout 输出,这样 Agent 无需手动通过管道传递,就能路由命令结果。支持三种接收端:
| 接收端 | 效果 |
|---|---|
stdout | 默认;仅写入 stdout |
file:<path> | 将输出原子地写入 <path>(临时文件 + 重命名) |
webhook:<url> | 将输出正文 POST 到 URL(使用 --compact 时为 application/json 或 application/x-ndjson) |
遇到未知协议时会拒绝请求,并返回结构化错误,列出支持的协议。Webhook 请求失败时会返回非零状态码,并在 stderr 中记录 URL + HTTP 状态码。
命名配置
配置是一组已保存的标志值,可在多次调用间重复使用。如果定时运行或重复运行的 Agent 每次使用不同输入,但重复使用相同的已保存标志,可使用配置。
table-reservation-goat-pp-cli profile save briefing --json
table-reservation-goat-pp-cli --profile briefing experiences list
table-reservation-goat-pp-cli profile list --json
table-reservation-goat-pp-cli profile show briefing
table-reservation-goat-pp-cli profile delete briefing --yes
显式标志始终优先于配置值;配置值优先于默认值。agent-context 会在 available_profiles 下列出所有可用配置,供执行内省的 Agent 在运行时发现它们。
退出代码
| 代码 | 含义 |
|---|---|
| 0 | 成功 |
| 2 | 用法错误(参数错误) |
| 3 | 未找到资源 |
| 5 | API 错误(上游问题) |
| 7 | 速率受限(等待后重试) |
| 10 | 配置错误 |
参数解析
解析 $ARGUMENTS:
- 为空、
help或--help→ 显示table-reservation-goat-pp-cli --help的输出 - 以
install开头 → 以mcp结尾 → 安装 MCP;否则 → 参见上方的先决条件 - 其他任何内容 → 直接使用(作为 CLI 命令执行,并带上
--agent)
安装 MCP 服务
- 安装 MCP 服务:
go install github.com/mvanhorn/printing-press-library/library/food-and-dining/table-reservation-goat/cmd/table-reservation-goat-pp-mcp@latest - 在 Claude Code 中注册:
claude mcp add table-reservation-goat-pp-mcp -- table-reservation-goat-pp-mcp - 验证:
claude mcp list
直接使用
- 检查是否已安装:
which table-reservation-goat-pp-cli如果未找到,请提供安装选项(参见此技能顶部的先决条件)。 - 将用户查询与上方“独特功能”和“命令参考”中的最佳命令匹配。
- 使用
--agent标志执行:table-reservation-goat-pp-cli <command> [subcommand] [args] --agent - 如果有歧义,深入查看子命令帮助:
table-reservation-goat-pp-cli <command> --help。