ESPN DeportesSan Francisco disfrutan de otra victoria y un récord invictoESPNCFB top 25 betting lines: Bama slim home favorite vs. UGA; Oregon favored vs. UCLAPunchPolice probe officers caught on hidden camera extorting Lagos dispatch riderThe Jerusalem PostWill Yemen's massive new anti-Houthi offensive succeed in bid to reclaim lost territory? - analysisDaily MaverickLOCAL ELECTIONS 2026: Manifesto test: IFP offers more financial support for traditional leadersRTP DesportoQuatro jogos, quatro vitórias. Seleção portuguesa em nova eraInquirerMarcos hopes Filipinos see sincerity in government effortsZDF heuteAktuelle Pressemitteilungen des ZDFRapplerRainy season over for 2026 as southwest monsoon ends3DNewsGoogle признала, что не все Android-приложения будут нормально работать на Googlebook с чипами Intel
The Daily Newsstand · Free, Always
Monday, October 5, 2026

Один мозг на два компьютера: память Claude Code на git и хуках

Translate

Вечером я дописал на ноутбуке кусок проекта, утром сел за пк и начал объяснять ассистенту, что вчера было сделано. Второй раз за неделю.

Память у него к тому моменту уже была. Папка с заметками на диске, он сам туда пишет и сам оттуда читает. Беда в том, что папка лежала на одном компьютере из двух.

Облако для этого ставить не хотелось, платить за синхронизацию заметок тем более. В итоге всё свелось к приватному репозиторию и двум хукам на двадцать строк bash.

Ниже: почему не подошли облачная папка, Obsidian Sync и плагин, как устроен скрипт, что сломалось по дороге и зачем вообще отдельное хранилище, если у Claude Code есть встроенная память.

Что за мозг и откуда он взялся

Я работаю в Claude Code. Два месяца назад я выделил ему папку и сказал, что он может писать туда всё, что нужно ему самому для работы со мной.

Сейчас там 114 заметок и 367 связей между ними: профиль, карточки проектов с цифрами, инфраструктура, журнал по датам, рабочие дни. Формат это обычный markdown, сверху Obsidian как читалка. Агенту Obsidian не нужен, ему хватает файлов.

Дальше про то, что с этим хозяйством пришлось сделать, чтобы оно работало на двух машинах.

Зачем отдельное хранилище, если есть встроенная память

Это первый вопрос, который мне задают, поэтому отвечу сразу.

Встроенная память у Claude Code есть, она лежит в ~/.claude/projects/<проект>/memory/, там файл-индекс MEMORY.md и короткие заметки рядом. Индекс подгружается в каждую сессию автоматически.

Проблем с ней три, и все про границы.

Она привязана к машине. Каталог лежит в системном профиле пользователя, на второй компьютер сам по себе не попадает.

Она привязана к проекту. Папка заводится под рабочую директорию, а мои факты не про один проект. Где лежит какой диск, что было на созвоне в августе, какие цифры в резюме, всё это переезжает из задачи в задачу.

Она короткая по устройству. Индекс грузится целиком в каждую сессию, значит расти ему некуда. Это оглавление, а не база.

Поэтому у меня работает и то, и другое. Встроенная память держит несколько строк вида «подробности лежат в таком-то хранилище», а само хранилище живёт отдельным репозиторием и может быть сколько угодно большим. Одно не заменяет другое.

В хранилище важен не объём, а роутинг

Соблазн очевидный: скормить агенту всё, что есть. Так делать нельзя, и не из-за лимитов, а потому что на забитом контексте модель начинает путать соседние факты и цепляться за то, что обсуждали пять экранов назад.

Мой вариант папок

Мой вариант папок

Поэтому главный файл хранилища это не оглавление, а таблица маршрутизации. Выглядит так:

Запрос про

Открыть

кто я, опыт, образование

01 - Профиль/Профиль

мои проекты и цифры по ним

02 - Проекты/00 - Карта проектов

любой текст для отправки людям

04 - Резюме и тексты/Анти-ИИ стиль

что где лежит на дисках, сервер

06 - Инфраструктура/Карта файлов

«что было тогда-то»

07 - Журнал по дате

Агент открывает этот файл, находит строку под задачу, идёт по ней и останавливается. Две заметки вместо ста четырнадцати.

Дальше огромный список запросов и данных

Дальше огромный список запросов и данных

Правила чтения и записи лежат в глобальном ~/.claude/CLAUDE.md, он подхватывается в любой сессии. Их три.

Читать точечно. Только то, на что указал роутинг. Хранилище целиком не читать, поиском по нему не сканировать без нужды.

Не спрашивать то, что уже записано. Если факт есть, использовать молча. Если он противоречит тому, что агент видит в файлах прямо сейчас, верить файлам и поправить заметку.

Все чаты клауда спрашивают, писать ли код за меня? И объясняют все блоки кода, написанные им.

Все чаты клауда спрашивают, писать ли код за меня? И объясняют все блоки кода, написанные им.

Дописывать после работы. Новый факт про человека в профиль, движение по проекту в карточку, значимая сессия в журнал. Даты абсолютные, «на прошлой неделе» через месяц не расшифровать.

Третье правило самое хрупкое, без него база протухает за две недели. Я довёл его до автоматизма отдельной строкой в конфиге: в конце ответа агент одним предложением говорит, что именно он записал. Эта строка нужна мне, чтобы видеть, что он не забыл.

Ещё одна мелочь, которая стоила мне вечера. Ссылки между заметками надо писать вики-ссылками, [[02 - Проекты/Название]]. Я долго ставил пути в обратных кавычках, и всё выглядело нормально ровно до того дня, когда я открыл граф: из 104 заметок 25 висели без единой связи, включая сам файл с роутингом. Граф видит только вики-ссылки.

Что я пробовал для синхронизации

Облачная папка. Внутри почти тысяча мелких файлов, которые правятся автоматикой по несколько раз за сессию. Облачные клиенты такое превращают в «START HERE (конфликтная копия).md». Отпало сразу.

Obsidian Sync. Платно и работает только через Obsidian.

Плагин Obsidian Git. Бесплатно и умеет всё нужное, но работает, только пока открыт сам Obsidian. Держать редактор запущенным ради фоновой синхронизации я не хочу, тем более на ноутбуке.

Хуки самого агента. На этом и остановился. Логика простая: хранилище нужно ровно в те моменты, когда я разговариваю с агентом. Значит, синхронизировать надо на старте сессии и после каждого ответа, а в остальное время можно вообще ничего не крутить.

Двадцать строк bash

Хранилище уехало в приватный репозиторий на GitHub. Первый коммит: 105 файлов, 0.86 МБ.

Дальше скрипт, который дёргается хуками.

#!/usr/bin/env bash
# sync.sh start - хук SessionStart: clone (если хранилища ещё нет) или pull
# sync.sh stop  - хук Stop: если есть изменения, commit, pull --rebase, push

BRAIN_DIR="${SECOND_BRAIN_DIR:-D:/Obsidian/Claude_brain}"
REPO_URL="${SECOND_BRAIN_REPO:-https://github.com/USER/second-brain.git}"
DEVICE="${SECOND_BRAIN_DEVICE:-$(hostname)}"

# Никаких интерактивных запросов логина из хука.
export GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never

# Хук передаёт JSON в stdin, он не нужен, просто вычитываем.
[ -t 0 ] || cat >/dev/null

g() { timeout 60 git -C "$BRAIN_DIR" "$@"; }
system_message() { printf '{"systemMessage": "%s"}\n' "$1"; }

start() {
  local status last
  if [ ! -d "$BRAIN_DIR/.git" ]; then
    if timeout 180 git clone -q "$REPO_URL" "$BRAIN_DIR" >/dev/null 2>&1; then
      status="впервые скачан с GitHub"
    else
      echo "[Второй мозг] Пока недоступен: нет репозитория или сети."
      return 0
    fi
  elif g pull -q --rebase --autostash >/dev/null 2>&1; then
    status="обновлён"
  else
    g rebase --abort >/dev/null 2>&1
    status="НЕ обновлён (нет сети или конфликт), работаешь с локальной копией"
  fi
  last=$(g log -1 --format='%cd, %s' --date=format:'%Y-%m-%d %H:%M' 2>/dev/null)
  echo "[Второй мозг] $status. Путь: $BRAIN_DIR. Последний коммит: ${last:-нет}."
}

stop() {
  [ -d "$BRAIN_DIR/.git" ] || return 0
  if [ -n "$(g status --porcelain 2>/dev/null)" ]; then
    g add -A >/dev/null 2>&1
    g commit -q -m "$DEVICE: автосинк $(date '+%Y-%m-%d %H:%M')" >/dev/null 2>&1
  fi
  local ahead
  ahead=$(g rev-list --count '@{u}..HEAD' 2>/dev/null) || return 0
  [ "${ahead:-0}" -gt 0 ] || return 0
  if ! g pull -q --rebase --autostash >/dev/null 2>&1; then
    g rebase --abort >/dev/null 2>&1
    system_message "Второй мозг: не удалось подтянуть изменения перед отправкой."
    return 0
  fi
  g push -q >/dev/null 2>&1 ||
    system_message "Второй мозг: push не удался, изменения уйдут в следующую синхронизацию."
}

case "$1" in
  start) start ;;
  stop) stop ;;
  *) echo "usage: sync.sh start|stop" >&2; exit 2 ;;
esac
exit 0

Подключается в ~/.claude/settings.json:

{
  "hooks": {
    "SessionStart": [
      { "hooks": [ {
          "type": "command",
          "command": "C:/Program Files/Git/bin/bash.exe",
          "args": ["C:/Users/USER/.claude/second-brain/sync.sh", "start"],
          "timeout": 200,
          "statusMessage": "Синхронизирую второй мозг…"
      } ] }
    ],
    "Stop": [
      { "hooks": [ {
          "type": "command",
          "command": "C:/Program Files/Git/bin/bash.exe",
          "args": ["C:/Users/USER/.claude/second-brain/sync.sh", "stop"],
          "timeout": 120,
          "async": true
      } ] }
    ]
  }
}

Четыре места, которые выглядят мелочью, но каждое из них я добавил не просто так.

GIT_TERMINAL_PROMPT=0 и GCM_INTERACTIVE=never. Хук выполняется в фоне, окна ввода логина вы не увидите. Увидите только зависший старт сессии и не поймёте почему. Там же timeout на каждый вызов git, чтобы мёртвая сеть не стоила двух минут перед каждым ответом.

--autostash. Я часто правлю заметку руками в Obsidian и не коммичу, без этого флага pull будет падать.

[ -t 0 ] || cat >/dev/null. Агент передаёт хуку JSON в stdin. Если его не вычитать, скрипт рискует поймать SIGPIPE на ровном месте.

Вывод start уходит в stdout и попадает прямо в контекст модели. То есть агент с первых токенов знает, свежая у него база или он работает с локальной копией двухдневной давности. Ошибки в stop наоборот отдаются мне через systemMessage, потому что чинить их всё равно мне.

Коммиты подписаны именем машины: DESKTOP-7RNA8QS: автосинк 2026-09-29 22:28. По истории видно, где я сидел.

На ноутбуке настраивать не пришлось ничего. Тот же скрипт, тот же конфиг, первая сессия, и хранилище скачалось само.

Что сломалось

Два канала синхронизации подрались. Плагин Obsidian Git я не выключил, и какое-то время работали оба. Плагин тянет изменения слиянием, хук перебазированием. Кончилось тем, что посреди сессии плагин закоммитил правки агента, подтянул строки с ноутбука и оставил маркеры <<<<<<< внутри главного файла с роутингом. Разрешать пришлось руками и обязательно merge-коммитом, который надо сразу запушить, иначе pull --rebase из хука переигрывает тот же конфликт заново. Вывод банальный: канал должен быть один.

Абсолютные пути. Половина инфраструктурных заметок это строки вида D:\Obsidian\... и F:\ComfyUI\..., а на ноутбуке дисков D и F нет. Пришлось прямо в файл с роутингом написать, что пути ведут на пк, и завести отдельную заметку под ноутбук.

Коммит после каждого ответа. За длинный вечер набегает десяток коммитов «автосинк». Меня это устраивает, история мусорная, но честная. Кому мешает, легко добавит условие на минимальный интервал.

Что проверить перед тем, как класть личное в репозиторий

Ключей и токенов внутри не было, но нашлись строки вида «токены ботов лежат в таком-то файле на рабочем столе». Формально это не секрет, фактически это карта к секретам, и держать её стоит осознанно.

В .gitignore уехали .obsidian/workspace*.json, .trash/, системный мусор и, главное, .obsidian/plugins/*/data.json. Последнее неочевидно: плагины Obsidian держат в этих файлах ключи от сторонних API.

Приватность репозитория стоит проверить командой, а не памятью о том, какую кнопку вы нажимали.

Что это даёт и чего не даёт

Даёт вот что. Я сажусь за ноутбук, пишу в тот же мозг, вечером за пк он уже на месте. Агент не спрашивает мой стек по третьему кругу и помнит, чем кончился конкретный разговор в конкретный день. Побочный эффект оказался приятнее основного: за два месяца накопилась база фактов про себя с цифрами, и из неё неожиданно удобно собирать резюме.

Клауд сейчас можно сказать собирает информацию для моего резюме. Мне не нужно считать, изучать стэк, вспоминать решения. Клауд в курсе моего проекта, а значит информация о ней уже записана во втором мозге. Один промпт "обнови резюме", и мучения с актуализацией информации превратилось в автоматизированную систему сбора информации.

Не даёт вот чего. Умнее модель от этого не становится. Качество ответов упирается в качество заметок, а заметки пишет тот же агент под моим присмотром. Стоит пустить на самотёк, и через месяц там свалка, где на один вопрос лежит три ответа разной свежести. Поэтому правило про точечное чтение и правило про абсолютные даты я считаю не менее важными, чем весь git.

И отдельно: это не место для рабочих секретов. Репозиторий приватный, но приватный репозиторий это закрытая дверь, а не сейф.

Что дальше

Хочу раз в месяц прогонять хранилище на противоречия и устаревшие факты, руками я до этого не дохожу.

Если соберётесь повторять, начните не со скрипта. Синхронизация это двадцать строк на bash, а вот решить, какой запрос в какую заметку ведёт, за вас никто не сделает.

Также в следующих постах расскажу, как я клауду дал доступ к моим собеседованиям, и как это помогает мне разбирать ошибки и развиваться.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.