ClaudeMods
☰
ZH-CN
● 0 人在线 · 浏览 0 次
赞助提交作品
GitHub 仓库 · 发布者 KeygripGit

workorder-pane — Keygrip 在 Claude Code 中的 work order

一个在面板中显示 Keygrip client 部署队列的 Claude Code 插件:/workorders 列出 work order,Reader 将每笔拆成 Overview、Fields、Edits、Schema、Verify、Notes 和支持 live/proposed 切换的服务器渲染 Preview 分页。可通过插件市场、--plugin-dir/CLAUDE_CODE_PLUGIN_DIRS 路径或 Windows 设置副本安装;通过 $.http.fetch 使用项目 key 调用远程 client MCP server。

KeygripGit@KeygripGit

KeygripGit/claude-mods/tree/main/plugins/workorder-pane

已翻译

关于这个 mod

workorder-pane — Keygrip 在 Claude Code 中的 work order

这是一个 Claude Code 插件(由 function hooks 组成,见 docs/claude-code-mods.md),把 client 的部署流程画在面板里,而不是在工具列中铺一大片 Markdown。追踪 issue #1516。

/workorders          # 已连接项目的所有 work order 队列
/workorders 502      # 按 optimization id 直接进入一笔 work order

它显示什么

队列。 kg_workorders 的每笔 work order 显示为一行:id、version、mode、state、keyword。被阻塞的行会变暗且不能打开(服务器也会拒绝)。r 刷新,s 显示/隐藏已被取代的版本。

Reader(选择一行)只获取一次 kg_fetch_workorder,再按固定标题拆分文件。用 1–7 切换分页,b 返回队列:

| 分页 | 显示 | | --- | --- | | 1 Overview | mode、准备日期、keyword 目标、“改了什么”、主图 | | 2 Fields | 每个可部署值放在代码块中,显示相对于 SEO 限制的长度计,超限变红;与实时页面相同时显示 unchanged,并可复制 | | 3 Edits | 每个正文修改都框出 why、where、Find 文本和 Replace/Insert HTML,并可复制;新 work order 显示完整正文 | | 4 Schema | 去掉 script 外壳的 JSON-LD,并可复制 | | 5 Verify | 发布后步骤以切换项显示,并显示已勾选数量 | | 6 Notes | 此版本以来的上下文变化、建议但未应用、已检查并保持不动 | | 7 Preview | 由服务器上的 kg_workorder_preview 渲染页面(打开 work order 的瞬间就开始渲染第一个切片,因此通常立即显示):p 切换 live(当前提供的页面)和 proposed(在浏览器中应用 work order 修改,每项修改用品牌青色框出,删除用红色虚线标记);n/u 在 1600 px 切片间移动,r 重新渲染。终端显示像素(kitty/Ghostty)。桌面/VS Code 在 Svg 中显示半尺寸 JPEG,并链接到 app.keygrip.ai 上同一个预览页面。 |

底部的 Live URL 字段提交时以 target: manual 调用 kg_report_deployed。空 URL 会被拒绝。该插件不会写入其他内容。

安装(client 及 monorepo 外部用户)

应用会把此文件夹作为 Claude Code 插件市场提供(web/mods.py,#1516):GET /mods/marketplace.json 把 app/mods/ 下的每个 mod 列为 archive 来源,GET /mods/<name>-<version>.zip 按需压缩 mod(确定性生成、按 process 缓存,manifest 中有 sha256)。它像 /healthz 一样公开:client 不需要 GitHub 账户,机器上也不需要 git。面向 client 的指南是 /mods/(桌面点击路径和终端命令);项目的 Client MCP access box 会打印两个命令和待粘贴的 key:

claude plugin marketplace add https://app.keygrip.ai/mods/marketplace.json
claude plugin install workorder-pane@keygrip

面板通过 $.http.fetch 自己调用 https://app.keygrip.ai/client/mcp:每个工具一个 JSON-RPC tools/call POST,使用项目 kg_client_ key 作为 Bearer header。它只在面板中询问一次 key,并存入插件自己的 $.store(在队列按 k 可更换)。manifest 故意不声明服务器:按钮发出的工具调用会被 Auto 模式权限分类器拒绝(“产生此动作的请求没有要求它”),即使插件自带服务器也在桌面上测过;否则每个 client 都得粘贴 allow list,而 manifest server 又需要通过 /plugin configure 传入 key。直接 fetch 两者都不需要——在 2026-10-03、--permission-mode auto 下测得如此。端点无状态并返回 JSON,所以没有 handshake。每次要让安装取得变更,都要在 plugin.json 中提升 version:安装会固定看到的版本,claude plugin update 只有数字变化才会移动,zip URL 也会带版本。

⚠️ 通过 --plugin-dir/CLAUDE_CODE_PLUGIN_DIRS 加载的插件会覆盖同名的市场安装(随后 claude plugin install --config 会报告“failed to load after install”);开发机上只能选一个。

从 checkout 加载(开发者)

CLI,单个会话: claude --plugin-dir app/mods/workorder-pane

CLI 或桌面,始终加载: 在 CLAUDE_CODE_PLUGIN_DIRS 指定文件夹,可放在 process environment 或 ~/.claude/settings.json 的 env 区块中(这是用户文件,不是项目文件)。

Windows 上的 Claude Desktop 使用自己的引擎和 %USERPROFILE%.claude,所以需要 Windows 路径。当前可用的副本:

// C:\\Users\\<you>\\.claude\\settings.json
{
  "env": { "CLAUDE_CODE_PLUGIN_DIRS": "C:\\\\Users\\\\<you>\\\\.claude\\\\mods\\\\workorder-pane" },
  "permissions": { "allow": [
    "mcp__keygrip-workorder__kg_workorders",
    "mcp__keygrip-workorder__kg_fetch_workorder",
    "mcp__keygrip-workorder__kg_articles",
    "mcp__keygrip-workorder__kg_article_status",
    "mcp__keygrip-workorder__kg_workorder_preview"
  ] }
}

(市场安装的 server 是这些规则中的 plugin_workorder-pane_keygrip-workorder。)allow 清单只在上述 developer 路径的 Auto 权限模式中重要:面板的 MCP 调用来自按钮而不是提示,auto-mode 分类器没有可匹配内容,所以会拒绝。允许的工具会跳过分类器。写入工具 kg_report_deployed 刻意不在 allow 中;从面板报告部署时请关闭 Auto 或批准提示。

在 WSL 中变更后同步 Windows 副本:

rsync -a --delete --exclude .cache --exclude '.claude-plugin/types' --exclude tsconfig.json \
  app/mods/workorder-pane/ /mnt/c/Users/<you>/.claude/mods/workorder-pane/

它连接的 MCP server

keygrip-workorder —— https://app.keygrip.ai/client/mcp,使用项目范围的 kg_client_ key(claude mcp add --transport http keygrip-workorder <url> -H "Authorization: Bearer kg_client_…")。server 名称就是 $.mcp.call 使用的名称;桌面应用也需要在自己的 .claude.json 中配置同名 server。创建 key 的位置是应用中的项目设置,issue #1071。

Preview 如何生成

笔记本上不会运行任何内容。client MCP server 的 kg_workorder_preview(optimization_id, mode, slice, format, scale)(内部 /mcp 也提供同一工具)会调用 GET /api/v1/optimizations/{id}/preview,由 content/page_preview.py 提供。应用自己的 Chromium 加载 run 的 page_url;proposed 模式按 CMS 编辑器使用者遵循的规则把 work order 的 BodyEdit 应用到 live DOM(按含义查找,区段延续到下一个同级标题,按顺序应用修改),再以 1280×1600 切片截取页面。一次调用返回一个 image block 和一个 JSON block(slices、height、每项 edit 的 applied、view_url)。渲染在 web process 中按(run、version、mode)缓存 10 分钟。Web twin 是 …/studio/runs/<id>/preview/?mode=proposed:堆叠全部切片并列出每项修改结果;这就是桌面面板链接的 view_url。

终端像素仍需要 kitty ≥ 0.28 或 Ghostty(见 docs/claude-code-mods.md)。

开发

claude plugin validate app/mods/workorder-pane   # manifest + module hooks/calls
claude plugin test     app/mods/workorder-pane   # hooks/*.test.tsx against the engine

parser(hooks/parse.ts)按文档标题取键;hooks/fixture.ts 是符合这种形状、以 optimization 502 为模型的精简 work order。validator 强制的规则每项都消耗一轮:$ 只能传给顶层函数声明;atom() 引用需要字面 plugin 字符串;Button 只能有一个字符串子节点或 label;fetch 必须从 command 或 button handler 开始,不能从 render hook 开始(draw 的异步链中的写入会被静默丢弃)。

尚未构建

  • server 旁还没有结构化 JSON,因此可以移除标题 parser。
  • net-new page(还没有 live URL)没有 proposed render:改为在 Keygrip 自己的 preview template 中渲染正文。
  • 如果每 process 的 render cache 在两台 web box 之间太冷,还没有共用 render cache(R2 或 Postgres)。

安装

请先查看作者 README 确认 marketplace 和插件名称;命令可能随仓库结构改变。

claude plugin marketplace add KeygripGit/claude-mods
claude plugin install workorder-pane
原文 / README

workorder-pane — Keygrip work orders inside Claude Code

A Claude Code mod (a plugin of function hooks, see docs/claude-code-mods.md) that draws the client deploy loop in a pane instead of a wall of markdown in a tool row. Tracks issue #1516.

/workorders          # the queue: every work order the connected project has
/workorders 502      # straight to one order by optimization id

What it draws

Queue. One row per work order from kg_workorders: id, version, mode, state, keyword. Blocked rows are dimmed and refuse to open (the server refuses them too). r refresh, s show/hide superseded versions.

Reader (pick a row). Fetches kg_fetch_workorder once and splits the document on its fixed headings. Tabs on 1–7, b back to the queue:

| Tab | Shows | |---|---| | 1 Overview | mode, prepared date, keyword target, "what changed", hero image | | 2 Fields | each deployable value in a code block, a length meter against its SEO limit (red when over), unchanged when it matches the live page, a copy button | | 3 Edits | each body edit boxed: why, where, the Find text and the Replace/Insert HTML, a copy button; a net-new order shows the full body | | 4 Schema | the JSON-LD with the <script> wrapper stripped, a copy button | | 5 Verify | the post-publish steps as toggles, with a checked count | | 6 Notes | context changed since this version, recommended-not-applied, checked-and-left-alone | | 7 Preview | the page rendered on the server by kg_workorder_preview (the first slice starts rendering the moment an order is opened, so the tab usually draws at once): p toggles live (as served now) and proposed (the work order's edits applied in the browser, each outlined in brand cyan, removals marked with a dashed red rule); n/u move through 1600 px slices, r re-renders. Terminal: pixels (kitty/Ghostty). Desktop/VS Code: a half-scale JPEG inside an Svg, plus a link to the same preview as a page on app.keygrip.ai |

At the bottom, a Live URL field whose submit calls kg_report_deployed with target: manual. It refuses an empty URL. Nothing else in the mod writes.

Installing it (clients, and anyone outside the monorepo)

The app serves this folder as a Claude Code plugin marketplace (web/mods.py, #1516): GET /mods/marketplace.json lists each mod under app/mods/ as an archive source and GET /mods/<name>-<version>.zip is the mod zipped on demand (deterministic, cached per process, sha256 in the manifest). Public, like /healthz: a client needs no GitHub account and no git on the machine. The client-facing guide is /mods/ (desktop click path, terminal commands); the project's Client MCP access box prints the two commands and the key to paste:

claude plugin marketplace add https://app.keygrip.ai/mods/marketplace.json
claude plugin install workorder-pane@keygrip

The pane talks to https://app.keygrip.ai/client/mcp itself — one JSON-RPC tools/call POST per tool over $.http.fetch, the project's kg_client_ key as the Bearer header — and asks for that key once, in the pane, keeping it in the plugin's own $.store (k on the queue changes it). It deliberately does not declare the server in the manifest: a tool call made from a button is refused by the Auto-mode permission classifier ("the request that produced this action did not ask for one"), measured on the desktop with a plugin-bundled server too, which would make every client paste an allow list; and a manifest server needs the key through /plugin configure. A direct fetch needs neither — measured under --permission-mode auto on 2026-10-03. The endpoint is stateless and answers JSON, so there is no handshake. Bump version in plugin.json with every change you want installs to pick up: an install pins to the version it saw, claude plugin update only moves when the number does, and the zip URL carries the version.

⚠️ A plugin loaded through --plugin-dir / CLAUDE_CODE_PLUGIN_DIRS overrides a marketplace install of the same name (and claude plugin install --config then reports "failed to load after install"); on a developer machine use one or the other.

Loading it from the checkout (developers)

CLI, one session: claude --plugin-dir app/mods/workorder-pane

CLI or desktop, always: name the folder in CLAUDE_CODE_PLUGIN_DIRS, in the process environment or the env block of ~/.claude/settings.json (the user file, never a project's).

Claude Desktop on Windows runs its own engine with its own %USERPROFILE%\.claude, so it needs a Windows path. The copy that works today:

// C:\Users\<you>\.claude\settings.json
{
  "env": { "CLAUDE_CODE_PLUGIN_DIRS": "C:\\Users\\<you>\\.claude\\mods\\workorder-pane" },
  "permissions": { "allow": [
    "mcp__keygrip-workorder__kg_workorders",
    "mcp__keygrip-workorder__kg_fetch_workorder",
    "mcp__keygrip-workorder__kg_articles",
    "mcp__keygrip-workorder__kg_article_status",
    "mcp__keygrip-workorder__kg_workorder_preview"
  ] }
}

(For a marketplace install the server is plugin_workorder-pane_keygrip-workorder in those rules.) The allow list matters in Auto permission mode only for the developer path above, where the tools come from a hand-configured server: the pane's MCP calls come from a button, not a prompt, so the auto-mode classifier has nothing to match them against and refuses them ("the request that produced this action did not ask for one"). Allowed tools skip the classifier. The write tool kg_report_deployed is deliberately not allowed; switch the session off Auto, or approve the prompt, when you report a deploy from the pane.

Sync the Windows copy from WSL after a change:

rsync -a --delete --exclude .cache --exclude '.claude-plugin/types' --exclude tsconfig.json \
  app/mods/workorder-pane/ /mnt/c/Users/<you>/.claude/mods/workorder-pane/

The MCP server it talks to

keygrip-workorder → https://app.keygrip.ai/client/mcp with a project-scoped kg_client_ key (claude mcp add --transport http keygrip-workorder <url> -H "Authorization: Bearer kg_client_…"). The server name is what $.mcp.call is given; the desktop app needs the same server in its .claude.json. Minting the key: project settings in the app (issue #1071).

How the preview is made

Nothing runs on the laptop. kg_workorder_preview(optimization_id, mode, slice, format, scale) on the client MCP server (and the same tool on the internal /mcp) calls GET /api/v1/optimizations/{id}/preview, which content/page_preview.py serves: the app image's own Chromium loads the run's page_url, and in proposed mode runs the work order's BodyEdits against the live DOM by the same rules a person follows in the CMS editor (find by meaning, a section runs to the next heading of the same level, edits apply in order), then screenshots the page in 1280×1600 slices. One call returns one slice as an image block plus a JSON block (slices, height, applied per edit, view_url). Renders are cached ten minutes per (run, version, mode) in the web process. The web twin is …/studio/runs/<id>/preview/?mode=proposed, which stacks every slice and lists each edit's outcome; that is the view_url the desktop pane links to.

Pixels in the terminal still need kitty ≥ 0.28 or Ghostty (see docs/claude-code-mods.md).

Developing

claude plugin validate app/mods/workorder-pane   # manifest + what the module hooks/calls
claude plugin test     app/mods/workorder-pane   # hooks/*.test.tsx against the engine

The parser (hooks/parse.ts) keys on the document's headings; hooks/fixture.ts is a compact work order in that shape, modelled on optimization 502. Rules the validator enforces that cost a round each: $ may only be passed to a top-level function declaration; atom() references need literal plugin strings; a Button takes one string child or label; a fetch must start from a command or button handler, never from the render hook (a write from the draw's async chain is dropped silently).

Not built

  • Structured JSON from the server beside the markdown, so the heading parser can go.
  • A proposed render for a net-new page (no live URL yet): render the body in Keygrip's own preview template instead.
  • A shared render cache (R2 or Postgres) if the per-process one proves too cold across the two web boxes.

更多类似作品