Комментарии 3
Handoffs + Locks + Mailbox - по сути переизобрели Chubby/ZooKeeper на файлах. И это комплимент, не критика. Для координации параллельных сессий на одной машине файловая система - самый надежный транспорт.
У нас похожая задача, но другой масштаб: не сессии одного разработчика на одной машине, а разные люди в разных IDE (Claude Code, Cursor, Windsurf) на разных машинах. Файловые локи тут не работают, нужна сетевая координация.
Мы решили это через MCP-сервер с общей базой (CoAlly). Агент автоматически сохраняет контекст (что сделал, какие файлы тронул, почему так решил), другой агент находит это через семантический поиск. Не синхронная координация как у вас (агент A блокирует файл, агент B ждет), а асинхронная (агент A записал контекст, агент B прочитает когда понадобится).
Ваш подход с heartbeat для мертвых процессов правильный. Мы на это напоролись с другой стороны: если MCP-сессия падает посередине save_session_context, запись может остаться без эмбеддинга. Решили через async write - эмбеддинг генерируется в фоне, агент не ждет.
mclaude + CoAlly кстати могли бы хорошо дополнять друг друга: mclaude для синхронной координации сессий, CoAlly для долгосрочной памяти между ними.
Спасибо за разбор, параллель с Chubby/ZooKeeper отличная. Я сама её так чётко не формулировала, но если переводить стек получается:
Locks ≈ Chubby session lease
INDEX.md append-only ≈ WAL
Mailbox ≈ SMTP / RFC 822
Heartbeat ≈ lease renewal
Становится понятнее, когда подход работает (POSIX FS, одна машина) и когда ломается (NFS, распределённость). Добавлю явным сопоставлением в следующую итерацию документации.
Про cross-machine уточню, у меня три рабочих сценария:
Одна локальная машина, несколько параллельных сессий Claude Code одного человека.
Общий сервер по SSH, несколько Claude-инстансов одновременно: координация через файлы работает как на локальной машине.
Общий git-репозиторий между машинами:
.claude/handoffs/и chronicles под git, SessionStart hook делает pull, обмен асинхронный с задержкой в частоту пушей.
Где ломается: несколько разработчиков на разных физических машинах через сетевые FS (NFS/SMB) с попыткой работать в одной общей папке. O_CREAT|O_EXCL там теряет атомарность. Для синхронной координации в реальном времени между разными машинами нужен сетевой координатор уровня вашего MCP-сервера, file-based не вытянет.
Ваша проблема,запись без эмбеддинга при падении,у меня не возникает, эмбеддингов нет вообще. Но partial-write recovery для handoffs / мейлбокса / локов сейчас не идеален: сессия может умереть посреди записи и оставить полузаписанный markdown, который другая сессия попробует распарсить. Решается просто:
def atomic_write(path, content): tmp = path.with_suffix(path.suffix + ".tmp") tmp.write_text(content, encoding="utf-8") os.fsync(open(tmp).fileno()) tmp.replace(path) # POSIX atomic on same FS tmp = path.with_suffix(path.suffix + ".tmp")
tmp.write_text(content, encoding="utf-8")
os.fsync(open(tmp).fileno())
tmp.replace(path) # POSIX atomic on same FS
Добавлю в mclaude в ближайшую итерацию.
Про комплементарность согласна. Моя архитектура хорошо ложится на синхронную координацию в пределах одной FS (lock-then-act, немедленный handoff), ваша на асинхронную долгосрочную память с семантическим поиском между разными инструментами и машинами. Это разные слои, не конкуренция.
Думаю над адаптером в одну сторону: mclaude_export_to_coally.py, который читает handoffs и пушит в MCP-сервер. Тогда у команд, которым нужна память cross-IDE, есть путь без переписывания координации.
Из вашего комментария возьму три вещи: (1) явное сопоставление примитивов в распределённые аналоги, (2) atomic write по всему mclaude, (3) развести sync / async режимы как явные API, а не побочный эффект реализации. Полезный фидбек, спасибо.

Несколько Клодов над одним проектом: locks, handoffs и email 1982 года