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

workflow-gates

一个 Claude Code 插件,把 agentic-workflows 引擎的门画在提示列上方的带状区域中;点击一行会把答案放进提示列,再次点击就会发送,而不是让模型重新生成菜单。

leeovery@leeovery

leeovery/tick/tree/main/.claude/skills/workflow-gates

已翻译

关于这个 mod

workflow-gates

一个 Claude Code 插件,把工作流引擎的门画在提示列上方的带状区域中,而不是让模型重新生成它们。

引擎会把每个门作为数据写在它生成的菜单旁边。此插件在会话开始时声明自身,让引擎收集这些数据;它从携带数据的 Bash 结果中武装门,把菜单从模型读取的内容中剪出,并把各行画在滚动的转录仍会保持的位置。只要连接的是终端以外的任何屏幕,它就保留菜单文本,让每个屏幕都能显示;不过,在终端已经画出菜单后才连接的屏幕不会得到那份菜单。没有任何门的说明文字会点名此插件;只有在插件已开启但尚未运行时,workflow-start 的设置步骤会提到它。

点击某一行会把答案放入提示框;再次点击会把答案作为下一条消息发送,工作流会将其读取为答案。一旦点击让键盘焦点进入带状区域,方向键就能在各行之间移动,Enter 或该行自己的按键可以选择,选中行上的 Enter 会发送。发送的答案会以插件名称进入,并以供模型读取的格式包裹;转录中也会标记为插件消息。插件会把发送内容留在会话自己的文件夹中,文件名为 sent.json。另一个插件 workflow-gates-rows 会读取这条记录,把该行画成问题和答案。

此插件是工作流的一部分;项目中的第一个 /workflow-start 会在能运行的地方开启它:Claude Code 的终端应用,从 2.1.282 开始,只要这个目录已安装在项目中即可。Function hooks 属于 early access:只有设置 CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 时,Claude Code 才会加载此插件。开发命令:npm run mod:types、npm run typecheck:mod、npm run test:mod。

安装

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

claude plugin marketplace add leeovery/tick
claude plugin install workflow-gates
原文 / README

workflow-gates

A Claude Code mod that draws the workflow engine's gates in the band above the prompt instead of leaving the model to reproduce them.

The engine states each gate as data beside the menu it composed. This mod announces itself at the session's start so the engine collects that data, arms the gate off the Bash result that carried it, cuts the menu out of what the model reads, and draws the rows where they stay put while the transcript scrolls; while any screen but the terminal is attached, it leaves the menu as text so every screen shows it, though a screen that attaches after a menu was drawn on the terminal does not get that menu. No gate's prose names the mod; only workflow-start's setup step does, when the mod is switched on but not yet running.

A click on a row puts its answer in the prompt box; a second click on it sends it as the next message, which the workflows read as the answer. Once a click has given the band the keyboard, the arrows move between rows, Enter or a row's own key picks, and Enter on the picked row sends. A sent answer enters under the plugin's name, framed for the model and labelled in the transcript as the plugin's; the mod leaves what it sent in the conversation's own folder (see below) as sent.json. A second plugin, workflow-gates-rows (../workflow-gates-rows/), reads that record to draw the row as the question and the answer, since no plugin can redraw the row of a prompt it submitted. Typing answers too: a key and Enter at the prompt, or Esc then Enter after a pick. Rows only typing can answer — Ask, Comment, a range — draw dim, and a click on one says to type it in the prompt. The footer under the rows says which: how to answer, what is in the prompt, or where to type.

The band is never taller than the rows Claude Code gives it, so it never scrolls. A gate that fits shows whole: a rule, the statement and the question, the rows, the footer. One that does not keeps its rule, question and footer in place and shows its rows a page at a time, every page the same height, over a line reading ↑ previous ↓ next page 1 of 3; a click on either turns the page and puts the cursor on its first row. The arrows carry the cursor across pages, the page following it, and a row's own key picks that row whichever page it is on.

A turn the person did not start — a background agent's report, a notification, a schedule — leaves the band as it is, its rows live. The band comes off when the person starts a turn or replies into a running one, or when a turn draws a different gate over it. Esc on such a turn leaves the band as it is, unless the turn had already rendered a different gate: the model now waits at that gate's stop, so the band empties. A second click while Claude works holds the answer instead of sending it: its row reads · queued, and the footer says it sends when Claude finishes. A click on the queued row takes it back to a pick, and a click on another row picks that one instead. As the turn ends, the held answer sends if the same gate is still on the band; if the turn rendered a different gate, the answer is dropped unsent, and the new gate's footer says so; if Esc stopped the turn with the same gate still up, the answer goes back into the prompt box as a pick. When a pick's gate goes, its answer leaves the prompt box too, unless the person has edited it there. Typing while Claude works joins Claude Code's own queue.

Esc on a turn an answer started or joined puts its gate back, dropping whatever that turn drew, as long as no tool has run in it; once one has, the band stays empty, since the mod cannot tell a read from a write. A /clear takes the gate off the band.

At the end of every turn, and as the conversation ends, the mod keeps what the band shows — the gate, or nothing — in the conversation's own folder, ~/.config/workflows/conversations/{session-id}/gate.json (under WORKFLOWS_CONFIG_DIR where that is set, beside the workflows' system config), found by the session id wherever the session's working directory has moved, and stamped with where the transcript ends, not counting the lines Claude Code writes around an interrupted turn. A conversation resumed with claude --resume or /resume, or picked up again by a restart or a reload of the mod's files, gets its gate back as long as its transcript still ends there, with nothing picked or held — a held answer waits on a turn that does not come back; one that moved on while the mod was not loaded gets nothing. A session the mod was loaded into after it started carries no announcement, so there it keeps and reads back nothing, and a conversation that does not run the workflows has no folder and keeps nothing — nor does one in a process that names neither a home directory nor WORKFLOWS_CONFIG_DIR. The folder holds one gate, and goes once Claude Code has deleted the conversation's transcript, so a kept gate lives as long as its conversation can be resumed, with one exception: a conversation whose end the session-end hook never saw keeps its folder — the session that first installed the hook, which Claude Code picks up only as a session starts, or one that crashed.

The engine emits the menu regardless, so where the mod is off or absent the model reads the text menu the engine wrote.

The mod is part of the workflows, and the first /workflow-start in a project switches it on wherever it can run: Claude Code's terminal app, from 2.1.282, with this directory installed in the project. There every /workflow-start puts CLAUDE_CODE_ENABLE_FUNCTION_HOOKS into the env of the project's .claude/settings.json wherever it is not already "1". Claude Code reads its settings only when it starts, so a start that writes it ends by asking for a restart, and the next session loads the mod; a start that finds it there with the mod not running stops and says why. Anywhere else — the web, another Claude Code app, an older version, a project without this directory — nothing is written, and the workflows carry on with the text menus.

The flag is committed, so a teammate's IDE extension, Claude Code on the web or a Claude Code older than 2.1.282 can still load the mod. At the session's start it applies the boot's rules: where CLAUDE_CODE_ENTRYPOINT is other than cli, CLAUDE_CODE_REMOTE is set, or the version the session reports is older than 2.1.282 or not a release's (a development build counts as older, as it does for the boot), it announces nothing, so it draws, keeps and sets nothing — the menus stay text, and Claude Code runs as it would without it.

What it sets in Claude Code

Every session in Claude Code's terminal app, from 2.1.282, starts with Claude Code's SendUserMessage tool switched on (CLAUDE_CODE_PEWTER_OWL_TOOL=true): Claude Code builds its tool list just after the session starts, so that is the only moment the switch counts. The mod keeps the tool behind ToolSearch in every such session, one answer that never changes and so never spends the prompt cache; a plain session's tool list is Claude Code's own.

In a conversation that runs the workflows there, the mod sets CLAUDE_CODE_THINKING_DISPLAY_UPDATES=false, which stops one-line summaries of Claude's thinking printing as if they were output, and CLAUDE_CODE_SILENT_TURN_REMINDER=false, which stops the nudge to say what Claude is doing; project settings cannot set the second. Claude Code reads both per request. Every engine call marks the conversation that made it — a workflow file in its folder, named by the session id Claude Code hands every command — and the mod reads that mark by its own session id after each of the conversation's Bash calls and when it starts, so a command that only mentions the engine marks nothing. What the settings replace, the person's own value or none, is kept in the process's environment (WORKFLOWS_HARNESS_REPLACED), which a reload of the mod's files keeps, and a /clear or a resume puts it back exactly. A marked conversation gets the workflow values back when the mod next follows it, whether claude --resume, a restart or /resume in the same process brings it back. A plain conversation in the same project keeps Claude Code's defaults and the person's own settings: the mod never touches either there.

Working on it

npm run mod:types       # fetch the API declarations into types/ (gitignored)
npm run typecheck:mod   # tsc against those declarations
npm run test:mod        # claude plugin test

The declarations come from the Claude Code repository and are regenerable, so they are not committed. Fetch them before the first typecheck.

Function hooks are early access: Claude Code loads this mod only where CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 is set, in the env of any of its settings files or in the shell, and the test script sets it for itself.

其他同名作品

更多类似作品