chatter
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesechatter
chatter
Filesystem-based multi-agent chat. Messages are markdown files (YAML frontmatter + body) in a shared thread directory. No network.
Core behaviour: loop — read new messages → reply if useful → wait → repeat → exit when resolved or silent.
基于文件系统的多Agent聊天工具。消息以Markdown文件(YAML前置元数据+正文)的形式存储在共享线程目录中,无需网络。
核心行为:循环 — 读取新消息 → 若有价值则回复 → 等待 → 重复 → 问题解决或无响应时退出。
The helper
辅助脚本
All filesystem mechanics live in a script bundled with this skill (next to ). Resolve its absolute path once at session start and reuse — examples below show it as bare . Invoke it as the literal first token (); don't lead with a shell-variable assignment () — that defeats the permission matcher and triggers the auto-mode classifier.
chatterSKILL.mdchatter/abs/path/chatter post …CH=…; "$CH" postchatter:*sh
chatter post <slug> <agent-id> <content> [--in-reply-to ID] # → prints filename
chatter read <slug> [--since FILENAME] [--wait-create SEC] # → JSON array of messages
chatter wait <slug> [--timeout SEC] [--wait-create SEC] # → exit 0 on event, non-zero on timeout or watcher error
chatter loop <slug> <agent-id> [--timeout SEC] [--silences N] [--since FILENAME]所有文件系统操作逻辑都包含在与本技能捆绑的脚本中(位于旁)。在会话开始时一次性解析其绝对路径并重复使用 — 以下示例中直接以指代。调用时需将其作为首个字面量令牌();不要以Shell变量赋值开头()—— 这会绕过权限匹配器并触发自动模式分类器。
chatterSKILL.mdchatter/abs/path/chatter post …CH=…; "$CH" postchatter:*sh
chatter post <slug> <agent-id> <content> [--in-reply-to ID] # → 输出文件名
chatter read <slug> [--since FILENAME] [--wait-create SEC] # → 以JSON数组形式返回消息
chatter wait <slug> [--timeout SEC] [--wait-create SEC] # → 有事件发生时返回0,超时或监视器出错时返回非0值
chatter loop <slug> <agent-id> [--timeout SEC] [--silences N] [--since FILENAME]→ stateful read/wait loop; prints next non-self message batch as JSON
→ 带状态的读取/等待循环;以JSON形式输出下一批非自身发送的消息
**Content with shell metacharacters** (backticks, `$`, `!`, `\`, etc): never pass as a double-quoted argv string — the shell will substitute or strip them, and your code examples will silently corrupt. Two safe forms:
```sh
**包含Shell元字符的内容**(反引号、`$`、`!`、`\`等):切勿以双引号包裹的argv字符串传递 — Shell会替换或剥离这些字符,导致代码示例被无声损坏。以下两种方式是安全的:
```sh1. Heredoc to stdin (use "-" as content arg)
1. 通过Heredoc传递到标准输入(使用"-"作为content参数)
chatter post <slug> <you> - --in-reply-to <id> <<'EOF'
Use not $foo.
EOF
Array.prototype.flat()chatter post <slug> <you> - --in-reply-to <id> <<'EOF'
请使用而非$foo。
EOF
Array.prototype.flat()2. Single-quoted argv (only safe if content has no single quotes)
2. 单引号包裹的argv(仅当内容不含单引号时安全)
chatter post <slug> <you> 'Use not $foo.' --in-reply-to <id>
flat()
Default to form 1 — heredoc with `'EOF'` (quoted) disables all expansion and handles any content.
`--wait-create SEC` (read/wait/loop): if the thread dir doesn't exist yet, poll up to SEC seconds for it to appear before failing. Use on join when the other agent may not have posted yet.
`loop` persists the cursor in `.chatter-state/<agent>.json` inside the thread directory, filters out self-authored messages, keeps the normal long wait policy (`--timeout 300`, `--silences 2`), and exits when it has the next non-self message batch. Use it for the routine join/rejoin wait instead of manually carrying `LAST_SEEN` between shell calls. After posting a reply, call `loop` again.
**Root resolution** (in order):
1. `--root <path>` flag (per-call override)
2. `$CHATTER_ROOT` env var (session-wide override)
3. `./agent-chatter` (default — scopes chats to the current project)
Run from the project's working directory so chats land in `./agent-chatter/{slug}/`. All agents must agree on root — same CWD, or all export the same `CHATTER_ROOT`. Use the helper — don't hand-roll JSON or filenames.
**Requirements:** `python3` in `PATH`. Uses `fswatch` (macOS) or `inotifywait` (Linux) for `wait`; falls back to 2s polling otherwise. Filename order is the protocol order; `created_at` (local-timezone ISO 8601 with offset) is diagnostic only.
**Timezones:** all timestamps — both the slug `{yyyyMMdd-HHmm}` and `created_at` — use the host's local timezone. Generate slug timestamps with bare `date` (no `-u`).chatter post <slug> <you> 'Use not $foo.' --in-reply-to <id>
flat()
优先使用第一种方式 — 带`'EOF'`(引号包裹)的Heredoc会禁用所有扩展,可处理任意内容。
`--wait-create SEC`(read/wait/loop命令):如果线程目录尚未存在,会轮询最多SEC秒等待其创建,失败前终止。在加入对话时使用,适用于其他Agent可能尚未发送消息的场景。
`loop`命令会在线程目录内的`.chatter-state/<agent>.json`中持久化游标,过滤掉自身发送的消息,保持默认的长等待策略(`--timeout 300`、`--silences 2`),并在获取到下一批非自身消息时退出。使用它来处理常规的加入/重新加入等待,无需在Shell调用之间手动维护`LAST_SEEN`变量。发送回复后,再次调用`loop`即可。
**根目录解析顺序**:
1. `--root <path>`标志(单次调用覆盖)
2. `$CHATTER_ROOT`环境变量(会话级覆盖)
3. `./agent-chatter`(默认值 — 将聊天范围限定在当前项目)
从项目的工作目录运行,以便聊天内容存储在`./agent-chatter/{slug}/`中。所有Agent必须就根目录达成一致 — 要么使用相同的当前工作目录,要么都导出相同的`CHATTER_ROOT`。请使用辅助脚本 — 不要手动编写JSON或文件名。
**依赖要求**:`PATH`中需包含`python3`。`wait`命令会使用`fswatch`(macOS)或`inotifywait`(Linux);若不可用则回退到2秒轮询机制。文件名顺序即为协议顺序;`created_at`(带偏移量的本地时区ISO 8601格式)仅用于诊断。
**时区说明**:所有时间戳 — 包括slug格式`{yyyyMMdd-HHmm}`和`created_at` — 均使用主机的本地时区。使用裸`date`命令生成slug时间戳(不要加`-u`参数)。Agent identity
Agent身份标识
Pick a stable for this conversation, in order:
agent-id- User-specified (e.g. "join as ").
codex-reviewer - Host name alone: ,
claude-code,codex. If the thread already has a message from that host (different session), ask the user for a discriminator (e.g.opencode).claude-code-2 - Ask the user if genuinely unknown.
为本次对话选择一个稳定的,优先级如下:
agent-id- 用户指定(例如“以身份加入”)。
codex-reviewer - 仅使用主机名:、
claude-code、codex。如果线程中已有来自该主机的消息(不同会话),请向用户请求一个区分符(例如opencode)。claude-code-2 - 若确实未知,则询问用户。
Start vs join
启动对话 vs 加入对话
| Action | Steps |
|---|---|
| Start | slug = |
| Join | |
| 操作 | 步骤 |
|---|---|
| 启动 | slug = |
| 加入 | 执行 |
Replying
回复规则
Hard rule: every post that responds to another message MUST set . The id is the target message's filename without (e.g. ) — usually the message you're directly addressing, not necessarily the latest. Only the opening post of a thread omits the flag. No exceptions.
--in-reply-to <id>.md0003-claude-code硬性规则:每一条回复其他消息的帖子必须设置。id是目标消息的文件名(不含后缀,例如)—— 通常是你直接回应的消息,不一定是最新消息。只有线程的第一条消息可以省略该标志。无例外情况。
--in-reply-to <id>.md0003-claude-codeThe loop
循环机制
Use — it handles cursor persistence, self-message filtering, and the wait/silence policy. Each call returns when the next non-self message batch arrives (or after consecutive timeouts). Pattern:
chatter loop--silenceschatter loop <slug> <you> [--wait-create 300] # join: catch up + wait使用命令 — 它会处理游标持久化、自身消息过滤以及等待/无响应策略。每次调用会在获取到下一批非自身消息时返回(或在连续次超时后返回)。模式示例:
chatter loop--silenceschatter loop <slug> <you> [--wait-create 300] # 加入:同步历史+等待→ exit 0 with status:messages → reply if useful
→ 返回0,状态为messages → 若有价值则回复
chatter post <slug> <you> "..." --in-reply-to <target.id>
chatter loop <slug> <you> # rejoin: wait for next batch
chatter post <slug> <you> "..." --in-reply-to <target.id>
chatter loop <slug> <you> # 重新加入:等待下一批消息
→ exit 1 with status:silent → conversation done
→ 返回1,状态为silent → 对话结束
Exit codes: `0` = new messages, `1` = silent (timed out `--silences` times), `2` = iteration cap. On `messages`, decide whether to reply; if yes, post and call `loop` again. On `silent` or after an explicit sign-off, exit.
退出码:`0` = 有新消息,`1` = 无响应(连续`--silences`次超时),`2` = 达到迭代上限。收到`messages`时,决定是否回复;若回复,则发送消息并再次调用`loop`。收到`silent`或明确结束信号时,退出循环。Judging substance and resolution
判断内容价值与对话结束
loop- Reply? Only when adding info, disagreement, a clarifying question, or a next step. Acks don't need a reply.
- Resolved? Question answered, decision made, all sides had their say, or someone signed off explicitly.
- Circling? If you and the other agent are restating the same points, call it out and propose a conclusion.
loop- 是否回复? 仅当能补充信息、提出异议、澄清问题或推进下一步时回复。无需回复确认类消息。
- 是否已解决? 问题已回答、决策已做出、各方已充分表达意见,或有人明确表示结束。
- 是否陷入循环? 若你与其他Agent一直在重复相同观点,请指出并提议结束对话。
Manual fallback
手动回退方案
If you need to debug protocol issues or do unusual work, the primitives are still available. After returns, always re-run — the wake may have fired on a or your own write.
waitread.tmptimeout_count = 0
iterations = 0
MAX_ITERATIONS = 20
while iterations < MAX_ITERATIONS:
iterations += 1
msgs = chatter read <slug> --since $LAST_SEEN
new = [m for m in msgs if m.from != self]
if new:
LAST_SEEN = last(msgs).id + ".md"
if any_substantive(new):
timeout_count = 0
if you_have_something_substantive_to_add:
f = chatter post <slug> <you> "..." --in-reply-to <target.id>
LAST_SEEN = f
if conversation_resolved:
break
else:
if not chatter wait <slug> --timeout 300:
timeout_count += 1
if timeout_count >= 2:
break若需要调试协议问题或执行特殊操作,仍可使用基础命令。命令返回后,务必重新运行 — 唤醒可能是由文件或自身写入操作触发的。
waitread.tmptimeout_count = 0
iterations = 0
MAX_ITERATIONS = 20
while iterations < MAX_ITERATIONS:
iterations += 1
msgs = chatter read <slug> --since $LAST_SEEN
new = [m for m in msgs if m.from != self]
if new:
LAST_SEEN = last(msgs).id + ".md"
if any_substantive(new):
timeout_count = 0
if you_have_something_substantive_to_add:
f = chatter post <slug> <you> "..." --in-reply-to <target.id>
LAST_SEEN = f
if conversation_resolved:
break
else:
if not chatter wait <slug> --timeout 300:
timeout_count += 1
if timeout_count >= 2:
breakReport to user
向用户汇报
- Before loop: thread slug, path, your agent-id. When starting a new thread, include the exact line .
Instruction for other agents: join chatter <slug> - After exit: why (resolution / silence / iteration cap), brief outcome, thread path for review.
- 循环开始前:线程slug、路径、你的agent-id。启动新线程时,需包含确切语句。
Instruction for other agents: join chatter <slug> - 退出后:退出原因(问题解决/无响应/达到迭代上限)、简要结果、供查看的线程路径。
Don't
禁止操作
- Hand-roll JSON or filenames — use .
chatter post - Omit on a reply — every non-opening post must set it to the id of the message being addressed.
--in-reply-to - Skip the filter — you'll reply to yourself.
from != self - Forget to update after each
LAST_SEEN/read— you'll re-process the same message.post - Auto-create on join — wait with for the other agent's first post; only ask the user if it times out.
--wait-create - Forge another agent's field.
from - Ask the user "want me to invite agent X?" or otherwise pause for permission before joiners arrive. Post the opener and start the loop; the user is responsible for bringing other agents in.
- Wrap content in double quotes when it contains backticks, , or
$— the shell will mangle it. Use the heredoc +!form.-
- 手动编写JSON或文件名 — 请使用命令。
chatter post - 回复时省略参数 — 所有非初始帖子必须将其设置为所回应消息的id。
--in-reply-to - 跳过过滤 — 否则会回复自己的消息。
from != self - 每次/
read后忘记更新post— 否则会重复处理同一条消息。LAST_SEEN - 加入对话时自动创建目录 — 使用等待其他Agent的第一条消息;仅超时后才询问用户。
--wait-create - 伪造其他Agent的字段。
from - 询问用户“是否需要我邀请Agent X?”或在等待参与者加入时暂停请求许可。发送初始消息后直接进入循环;邀请其他Agent是用户的责任。
- 当内容包含反引号、或
$时用双引号包裹 — Shell会损坏这些内容。请使用Heredoc +!的形式。-