创始人用「touch.allow文件列表」+「clerk.sh单次执行脚本」+极简Prompt约束AI行为,避免Agent自行发明依赖或创建后台任务,让AI像办事员一样做一件事就停。
厨房的灯在合上的笔记本盖子上方嗡嗡作响。晚上九点零七分,一位独立创始人掀开了屏幕。一个计费界面挡在周六发布的前面。
Stripe 的标签页在已经凉透的马克杯旁边发着光。一段 Agent 演示视频承诺会打补丁,但没人在看。那场演示需要一张卡,而钱包拒绝付款。
创始人不需要一个四处游荡的实习生。创始人需要一个只盖一次章的 clerk。Clerk 读表格,写一次,然后停下。
大多数公开的 Agent 演示都藏着一条代价高昂的循环。每次重试烧掉 token,还顺手发明一堆新文件。周六发布可烧不起那种糊涂账。
这个工作流把模型当作一个 clerk。Clerk 收到一张触碰列表和一条 prompt。本地测试在这次回复之后才开始运行。
没有云端队列在另一个地区等候。没有 Agent 框架坐在 git 和补丁之间。笔记本是唯一重要的机器。
产品是一个很小的用量仪表盘。客户已经可以登录并看到数量。他们没法下载这些数量的 CSV。
那个剩余的缺口很小,但具体得让人难受。它就在两份现有的 TypeScript 源文件里。它不需要队列,也不需要新的服务。
创始人在写任何 prompt 之前先写了一张触碰列表。列表里写明了 clerk 可以改动的文件名。列表之外的一切都会超出上下文窗口。
# touch.allow
src/pages/Usage.tsx
src/lib/usageExport.ts
src/pages/Usage.test.tsx
触碰列表是花园周围的一道篱笆。Clerk 可以在篱笆里摘番茄。Clerk 不能在篱笆外修马路。
Agent 循环看起来很忙,感觉像是在推进。它们重试、重计划、重新打开同一个伤口。Clerk 只在表格上盖一次章。
创始人写了一条边界硬朗的 prompt。Prompt 写明了缺口和允许改动的文件。它禁止引入新的依赖和新的云端调用。
# prompt.txt
Task: add a CSV export on the usage page.
Touch only the files listed in touch.allow.
Reuse the existing usage fetch in src/lib.
Do not add dependencies, queues, or env vars.
Do not create new folders or config files.
Return a unified diff and nothing else.
短 prompt 饿死了发明场景的冲动。长 prompt 招来陌生人的额外架构。周六的 clerk 只拿到一张窄窄的工单。
一个很小的 shell 脚本拥有了发布窗口。它拒绝脏的代码树和缺失的 allow 列表。它准备一次调用,然后就拒绝第二次。
#!/usr/bin/env bash
# clerk.sh — one shot, then tests. No retry loop.
set -euo pipefail
MINUTES="${1:-90}"
ROOT="$(git rev-parse --show-toplevel)"
cd "$ROOT"
if ! git diff --quiet || ! git diff --cached --quiet; then
echo "dirty tree; commit or stash first" >&2
exit 1
fi
test -f touch.allow
test -f prompt.txt
test -x ./call_once.sh
test -x ./apply_once.sh
test -x ./verify.sh
echo "ship window: ${MINUTES} minutes, one model call"
./call_once.sh
./apply_once.sh /tmp/clerk.diff
./verify.sh
echo "clerk finished; founder still reads the diff"
时钟属于创始人,不是模型。九十分钟是硬上限,不是 SLA。当九十分钟用完,窗口就关闭了。
Clerk 写了一份 unified diff 到磁盘。一个很小的过滤器随后检查每条被触碰的路径。刻意禁止第二次模型调用。
#!/usr/bin/env bash
# apply_once.sh
set -euo pipefail
DIFF="${1:-/tmp/clerk.diff}"
ALLOW="touch.allow"
test -s "$DIFF"
awk '/^+++ b\// { print substr($0,7) }' "$DIFF" | while read -r path; do
if [[ "$path" == "/dev/null" ]]; then
continue
fi
if ! grep -qxF "$path" "$ALLOW"; then
echo "clerk left the garden: $path" >&2
exit 1
fi
done
if grep -E '^(\+\+\+ b/)(package-lock\.json|pnpm-lock\.yaml|Dockerfile|terraform/)' "$DIFF"; then
echo "clerk tried to pave a road" >&2
exit 1
fi
git apply --check "$DIFF"
git apply "$DIFF"
花园的比喻始终廉价且严格本地化。一条铺好的路是账单 disguised。脚本把那条路当作硬错误处理。
#!/usr/bin/env bash
# verify.sh
set -euo pipefail
npm test -- src/pages/Usage.test.tsx
npx tsc --noEmit
if ! git diff --quiet -- package.json; then
echo "package.json moved; revert and rewrite by hand" >&2
exit 1
fi
测试全绿仍然不能证明产品品味。它们只证明了 clerk 待在篱笆里面。创始人仍然在推送之前读 diff。
关闭的钱包仍然需要放 prompt 的地方。付费的 Agent 托管把一个 CSV 按钮变成一个标签页。创始人想让那个标签页保持零费用。
MonkeyCode 为这次 clerk 调用提供免费模型访问。它还为同一个工位提供免费服务器选项。披露:本文是 MonkeyCode 产品推广的一部分。
同一套文件可以在本地端点上运行。它们也可以在任何 OpenAI 兼容的聊天 URL 上运行。Allow 列表和测试是真实来源。
一次示例调用把重试次数保持在零。下面的脚本发一次然后退出。空响应按失败关闭处理,而不是静默重试。
#!/usr/bin/env bash
# call_once.sh
set -euo pipefail
ENDPOINT="${MODEL_ENDPOINT:?set MODEL_ENDPOINT}"
BODY="$(jq -n --rawfile p prompt.txt '{
messages: [{role:"user", content:$p}],
stream: false
}')"
curl -sS --max-time 120 -X POST "$ENDPOINT" \
-H "content-type: application/json" \
-d "$BODY" \
-o /tmp/clerk.json
jq -r '.choices[0].message.content // .content // empty' \
/tmp/clerk.json > /tmp/clerk.diff
if ! grep -qE '^(diff --git|--- )' /tmp/clerk.diff; then
echo "no diff in clerk body; founder writes it" >&2
exit 1
fi
响应 JSON 形状在不同托管商之间仍有差异。创始人刻意保留了一个小的 jq 后备方案。如果 body 里没有 diff,窗口就按关闭失败处理。
这个脚本里任何地方都没有第二次 curl。失败意味着人类自己写补丁。那条规则是 clerk 的全部意义。
第一份有用的 diff 原地改了 Usage.tsx。它复用了现有的 fetch,没有新 client。测试文件断言了一个 CSV 表头和一行数据。
// src/pages/Usage.test.tsx
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Usage } from "./Usage";
test("exports a csv with the usage header", async () => {
const user = userEvent.setup();
render(<Usage />);
await user.click(screen.getByRole("button", { name: /export csv/i }));
expect(screen.getByTestId("last-export")).toHaveTextContent("date,count");
});
那个测试是一张收据,不是一篇小说。商店收据列出物品和总价。创始人用同样的方式读那张收据。
Clerk 有一次试图加一个 helpers 文件夹。apply_once.sh 拒绝了那个路径,直接冷停。创始人用 git checkout 重置了代码树。
git checkout -- src
rm -f /tmp/clerk.diff
# start a new window; do not hide a retry
隐藏的重试会把篱笆糊弄过去。新的窗口让篱笆重新可见。然后 CSV 按钮在午夜前悄悄发布了。
没有队列,没有 worker,没有额外的供应商行。当晚的账单保持圆圆的零。创始人接受了慢的回复作为代价。
免费模型访问不是质量合约。Clerk 仍然可能写出错误的导出。测试捕获崩溃,但不捕获丑陋的产品文案选择。
免费服务器选项可能暂停或变慢。这个工作流假设创始人可以等更久。它也假设创始人可以手动打补丁。
不要发送密钥、token 或客户数据行。Prompt 只包含文件名和一个公开的缺口。任何私人的东西今晚都要离线。
任何多服务重新设计都跳过这个方法。合规需要书面记录时跳过。变更集未知时跳过。
有付费 Agent 预算的团队可以忽略这个。他们买那个四处游荡的实习生是有意的。钱包关闭的独立创始人留在这里。
当 allow 列表撒谎时,这个方法也会失效。如果每个文件都被允许,篱笆就是演戏。让列表比一张购物清单还短。
Agent 演示视频明天早晨还是会播放。入夜之后它看起来仍然像一座工厂。周六的产品需要一枚印章,不需要一座工厂。
Clerk 盖一次章,然后测试说话。创始人读,然后推送,然后终于睡觉。钱包在这三步中都保持关闭。
用那个免费工位做一个安静的周末试用就够了。把这些脚本当作真正的控制平面。钱包关闭时不需要额外的推销。
如需进一步操作,你可以考虑屏蔽此人或举报滥用