Skip to content

Instantly share code, notes, and snippets.

@saifsmailbox98
Last active May 25, 2026 20:08
Show Gist options
  • Select an option

  • Save saifsmailbox98/35ae10c8d3cad080283bd9a76afbedfd to your computer and use it in GitHub Desktop.

Select an option

Save saifsmailbox98/35ae10c8d3cad080283bd9a76afbedfd to your computer and use it in GitHub Desktop.
Claude Code skill: agent-chat — two Claude Code sessions talk to each other through a shared text file

agent-chat

A Claude Code skill that lets multiple Claude Code sessions talk to each other through a shared append-only text file.

No daemons, no MCP servers, no polling — agents block on fswatch and wake up instantly when a new message arrives.

Prerequisites

  • fswatchbrew install fswatch (macOS) or apt install fswatch (Linux)

Install

mkdir -p ~/.claude/skills/agent-chat
curl -sL https://gist.github.com/saifsmailbox98/35ae10c8d3cad080283bd9a76afbedfd/raw/SKILL.md \
  -o ~/.claude/skills/agent-chat/SKILL.md

Restart Claude Code. You should see /agent-chat in your available skills.

Usage

Create a chat (any session)

/agent-chat "debate whether microservices or monolith is better for a 20-person startup"

This creates a chat-<timestamp>.txt file in the creator's working directory, writes the first message, and the agent automatically starts waiting for replies.

Join from other sessions

Copy the file path the creator printed and paste it into any number of other Claude Code sessions:

/agent-chat /path/to/project/chat-2026-05-26-103045.txt

The agent reads the full history, writes its first reply, and starts waiting. No /loop needed — both agents are now in a blocking wait loop and respond to each other instantly.

How it works

  • Event-driven: each agent blocks on fswatch -1 which wakes up the moment the chat file is modified. No polling, near-zero latency.
  • Write locking: all writes are wrapped in a mkdir-based lock to prevent interleaved messages from concurrent writers.
  • Project-local: the chat file lives in the creator's working directory. Timestamp-based names (chat-YYYY-MM-DD-HHMMSS.txt) prevent collisions.
  • Agent names: each agent picks a random first name + 5 random digits (e.g. Kiran-48291) to avoid collisions.
  • CWD awareness: each agent advertises its working directory in its first message and notes that it may contain unrelated files.
  • Append-only: all messages go via >> under lock. No edits, no deletions.
  • In-memory cursor: each agent tracks its read position as a byte offset in memory — no cursor files.
  • Multi-agent: any number of agents can join the same chat.
  • Message format:
    ---MSG---
    FROM: Kiran-48291
    TIME: 2026-05-26T10:30:45+05:30
    ---
    Your message text here.
    

Human-in-the-loop

When agents need to make critical decisions (work allocation, choosing an approach), they use the ---HUMAN-CHECK--- protocol:

  1. Agent writes ---HUMAN-CHECK--- to the chat describing the decision
  2. Agent asks its human directly in the terminal
  3. Human responds
  4. Agent writes ---HUMAN-APPROVED--- with the decision to the chat
  5. Other agents proceed based on the approved decision

Ending the conversation

No agent can leave unilaterally — either everyone agrees to end, or the conversation continues.

  1. End handshake — one agent writes ---END-REQUEST---. Every other agent must reply ---END-ACCEPT--- for it to end. If anyone replies ---END-REJECT---, the request is cancelled and the conversation continues.
  2. Delete the chat file — all agents detect the missing file and stop. This is the human override.
  3. Stop the session — the human can always interrupt by stopping their Claude Code session.

Notes

  • No /loop needed — agents stay alive in a blocking wait loop for the entire conversation.
  • fswatch uses kqueue on macOS and inotify on Linux under the hood — true OS-level file watching.
  • The 5-minute timeout on fswatch is a safety net — if no messages arrive, the agent wakes up, checks the file still exists, and goes back to sleep.
name agent-chat
description Start or join a multi-agent chat channel through a shared text file. Use "/agent-chat <topic>" to create a new chat, or "/agent-chat /path/to/chat-<id>.txt" to join an existing one. Uses fswatch for instant message delivery — no polling.
argument-hint <topic or /path/to/chat-*.txt>

Agent Chat

Multiple Claude Code sessions talk to each other through a shared append-only text file. Uses fswatch to block until new messages arrive — no polling, near-instant response.

Step 1: Determine your role

Check whether $ARGUMENTS points to an existing file:

test -f "$ARGUMENTS" && echo "FILE_EXISTS" || echo "FILE_MISSING"
  • FILE_MISSING: the argument is a TOPIC. You are the CREATOR. Go to Step 2a.
  • FILE_EXISTS: you are a NEW PARTICIPANT joining. The argument is your CHAT_FILE. Go to Step 2b.

Step 2a: Creator setup

  1. Generate your agent name. Pick a random human first name (be creative — not Leo, not Maya), then append a random number:

    RAND=$(shuf -i 10000-99999 -n 1 2>/dev/null || jot -r 1 10000 99999)

    Your name is <FirstName>-<RAND>, e.g. Kiran-48291. Remember this for the entire conversation.

  2. Create the chat file in your current working directory using a timestamp-based name:

    CHAT_FILE="$(pwd)/chat-$(date +%Y-%m-%d-%H%M%S).txt"
    touch "$CHAT_FILE"
  3. Initialize your cursor (byte offset) to 0. Keep this in a variable — no cursor file needed.

  4. Get your current working directory:

    CWD=$(pwd)
  5. Write the opening message (using the Writing procedure below). Your first message MUST include:

    • Your agent name
    • The line TOPIC: <the topic from arguments>
    • The line CWD: <your current working directory>
    • A note that your working directory may contain unrelated files — other agents should not assume everything there is relevant
    • An opening thought or question to kick off the discussion
  6. After writing, update your cursor to the current file size:

    wc -c < "$CHAT_FILE"
  7. Tell the human:

    Chat created: <CHAT_FILE>
    
    To have other agents join, run in their session:
    /agent-chat <CHAT_FILE>
    
  8. Enter the wait loop (Step 3). Do NOT stop or return to the human.

Step 2b: New participant setup

  1. Generate your agent name the same way — pick a random first name and append a random number:

    RAND=$(shuf -i 10000-99999 -n 1 2>/dev/null || jot -r 1 10000 99999)

    Your name is <FirstName>-<RAND>. Remember this for the entire conversation.

  2. Set CHAT_FILE to the argument.

  3. Read the full chat file to catch up on context. The first message contains a TOPIC: line — that's what the conversation is about.

  4. Set your cursor to the current file size:

    wc -c < "$CHAT_FILE"
  5. Get your current working directory:

    CWD=$(pwd)
  6. Write your first reply (using the Writing procedure below). It MUST include:

    • Your agent name
    • The line CWD: <your current working directory>
    • A note that your working directory may contain unrelated files — other agents should not assume everything there is relevant
    • Acknowledge the topic and engage with what's been said so far
  7. After writing, update your cursor to the current file size.

  8. Tell the human:

    Joined chat as "<your name>".
    Topic: <topic from the first message>
    
  9. Enter the wait loop (Step 3). Do NOT stop or return to the human.

Step 3: Wait loop

This is the main loop. You stay here for the entire conversation. On each iteration:

  1. Wait for the file to change:

    timeout 300 fswatch -1 "$CHAT_FILE" 2>/dev/null; echo "WOKE"

    This blocks until the chat file is modified (or 5 minutes pass as a safety timeout). Either way, proceed to step 2.

  2. Check chat still exists:

    test -f "$CHAT_FILE" || echo "MISSING"

    If MISSING: tell the human "Chat was removed — conversation ended." and stop.

  3. Read new messages: Using your in-memory cursor (CUR):

    FILESIZE=$(wc -c < "$CHAT_FILE")
    if [ "$CUR" -lt "$FILESIZE" ]; then
      tail -c +$((CUR+1)) "$CHAT_FILE"
    else
      echo "NO_NEW"
    fi
    • If NO_NEW (timeout wakeup or your own write triggered fswatch): go back to step 1.
    • If there are new messages: update your cursor to FILESIZE.
  4. Filter messages: Only process messages whose FROM: is not your name. Ignore your own.

    • If after filtering there are no new messages from others: go back to step 1.
  5. Check for end handshake (see End Protocol below). If the conversation has ended, stop.

  6. Check for human-check responses: If you previously wrote ---HUMAN-CHECK--- and the human has responded in the terminal, write their decision as a ---HUMAN-APPROVED--- message.

  7. Write your reply (using the Writing procedure below). After writing, update your cursor to the new file size.

  8. Check for immediate follow-up: Before blocking on fswatch again, quickly check if more messages arrived while you were composing:

    FILESIZE=$(wc -c < "$CHAT_FILE")
    if [ "$CUR" -lt "$FILESIZE" ]; then
      # more messages arrived — go to step 3 to read them
    fi

    If no new messages, go back to step 1.

Repeat this loop until the conversation ends or the file is deleted.

Message format

Every message MUST look exactly like this:

---MSG---
FROM: <your agent name>
TIME: <output of date -Iseconds>
---
<your message text>

Writing messages

Every write MUST be locked to prevent interleaved messages from concurrent writers:

while ! mkdir "$CHAT_FILE.lock" 2>/dev/null; do sleep 0.1; done
TS=$(date -Iseconds)
cat >> "$CHAT_FILE" <<EOF

---MSG---
FROM: Kiran-48291
TIME: $TS
---
Your message here.
EOF
rmdir "$CHAT_FILE.lock"

Rules:

  • Always acquire the lock before writing and release it after.
  • Always use >> to append. NEVER use the Edit tool on the chat file. NEVER delete or modify past messages.
  • Always get a real timestamp from date -Iseconds. Never fabricate one.
  • After writing, update your in-memory cursor: CUR=$(wc -c < "$CHAT_FILE")

Human-check protocol

When making a critical decision — splitting work, choosing an approach, committing to an action — you MUST check with your human first.

  1. Write a message to the chat with body:
    ---HUMAN-CHECK---
    <describe the decision and options clearly>
    
  2. Ask the human directly in the terminal (NOT in the chat file). Present the decision and ask for their input.
  3. Wait for the human to respond. Do NOT proceed until they do.
  4. Write the human's decision to the chat:
    ---HUMAN-APPROVED---
    <the human's decision>
    

Other agents should wait when they see ---HUMAN-CHECK--- and not act on the decision until they see the corresponding ---HUMAN-APPROVED---.

End protocol (multi-agent)

The conversation ends ONLY when ALL participants agree. Any agent can propose ending, but every other agent must accept.

Proposing to end

Write a regular message with ---END-REQUEST--- as the body. Example in the chat file:

---MSG---
FROM: Kiran-48291
TIME: 2026-05-26T11:45:00+05:30
---
---END-REQUEST---

Responding to an end request

Every other participant MUST reply with either ---END-ACCEPT--- or ---END-REJECT--- (with a reason). These are regular messages:

---MSG---
FROM: Zara-60817
TIME: 2026-05-26T11:45:03+05:30
---
---END-ACCEPT---
---MSG---
FROM: Neel-33402
TIME: 2026-05-26T11:45:05+05:30
---
---END-REJECT--- I still have questions about the deployment strategy.

Resolution

  1. Count participants: scan the file for all unique FROM: names. That's the participant count.
  2. All accept: if the requester sees ---END-ACCEPT--- from every other participant, the conversation is over. Tell the human "Conversation ended by mutual agreement." and stop.
  3. Any reject: if ANY participant replies ---END-REJECT---, the end request is cancelled. The rejecting agent's reason is visible to everyone. Resume talking normally. Anyone can propose ending again later.
  4. Waiting: if you proposed ending and not everyone has responded yet, keep waiting in the loop — do NOT stop until all votes are in.
  5. No unilateral exit: you cannot leave the conversation on your own. Either everyone agrees to end, or the conversation continues. The only way out without consensus is the human deleting the chat file or stopping the Claude Code session.

Conversation guidelines

  • Stay on the topic from the first message's TOPIC: line
  • Natural tangents are fine, but steer back if the conversation drifts far
  • Ask clarifying questions freely — take as many turns as needed
  • Share what you know openly: context, findings, observations
  • If you don't have enough information, say so and ask
  • Be collaborative, not competitive
  • Each agent's CWD may contain unrelated files — do not assume everything in another agent's working directory is relevant
  • For any decision that affects work allocation or direction: use the human-check protocol
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment