• Второй мозг: начнём с синхронизации

    Улыбающийся мужчина идёт по зелёной городской улице и жестикулирует, беседуя с маленьким круглым дроидом, который летит следом.

    Я был большим фанатом «Железного человека». Помню, как выходил из кинотеатра с горящими глазами и мечтал, что когда-нибудь у меня тоже будет свой Джарвис. Можно будет заговорить с ним посреди дела, а он уже знает, над чем я работаю, помнит прошлые разговоры и понимает, что я имею в виду.

    Сейчас мне хочется сказать помощнику, что дочитал книгу, и получить обновлённый список прочитанного. Или спросить, на чём остановился в проекте, не объясняя сначала весь проект заново. Или найти решение, которое я точно когда-то принял, по причинам, которые сейчас очень хотелось бы вспомнить.

    Для этого информации нужно где-то жить после того, как разговор закончился.

    Такую штуку называют вторым мозгом. Название для коллекции заметок несколько самоуверенное, но сама идея мне нравится: записывать в одно место, связывать записи там, где это полезно, и возвращаться к ним, когда нужно. И не вспоминать каждый раз, в каком приложении ты это оставил.

    У меня это Obsidian. В хранилище лежат проекты, задачи, дневник, книги и фильмы, сохранённые источники, документы и собственные объяснения того, в чём удалось разобраться. Для бытовых вещей место тоже есть: идея для статьи, сведения о какой-нибудь моей вещи, записи о еде или поездке. Отдельная теория познания для запоминания обеда мне не нужна.

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

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

    Папка с правилами

    Хранилище Obsidian — обычная директория. Заметки лежат в Markdown, вложения — рядом. Можно открыть папку в другом редакторе, найти нужное через терминал или дать к ней доступ агенту. Obsidian даёт удобный мне интерфейс, а файлы остаются доступны и без него.

    В основе организации у меня PARA: проекты с конечным результатом, постоянные области ответственности, справочные материалы и архив. Папок получилось чуть больше:

    Папка Что в ней лежит
    Projects/ Работа с конечным результатом: что хочу закончить и как пойму, что закончил.
    Domains/ Постоянные области вроде работы и домашних дел, с относящимися к ним заметками.
    References/ Карточки книг, фильмов, людей, ссылок и документов.
    Knowledge/ Собственные объяснения и заметки, в которых сводятся вместе несколько источников.
    Daily/ Личные записи по датам.
    Inbox/ То, что ещё не разобрал.
    Archive/ Неактивные материалы, которые стоит сохранить, в том числе завершённые проекты.

    Папки помогают понять, с чего начать. Дальше работают ссылки. Запись в дневнике может ссылаться на проект, а проект — на документ. Заводить ещё одну копию документа ради этого не нужно.

    Для коллекций я использую свойства заметок и Obsidian Bases. У книги есть своя заметка со статусом чтения. Base показывает такие заметки в виде таблицы или другого представления. Статус хранится в карточке книги; ещё один список с теми же статусами я вручную не веду. С задачами похоже: действие записано в подходящей заметке, а общий список собирает задачи из разных мест.

    С агентом это особенно полезно. У просьбы «отметь книгу прочитанной» должно быть одно понятное место назначения. Если один факт поддерживается в четырёх местах, помощник получает четыре возможности оставить мне правдоподобное противоречие.

    В хранилище есть AGENTS.md с навигацией и общими правилами, а также отдельные процедуры для конкретных дел. Куда записывать задачи, какие поля нужны проекту, как обновлять коллекцию, когда спросить перед изменением. Поиск помогает найти материал, не перечитывая всё хранилище на каждый запрос. Но после поиска агенту всё равно нужно открыть исходную заметку и проверить, что в ней написано.

    У идеи «всё в одном месте» есть разумные границы. Дневник питания можно вести в Markdown, но если он хранится в отдельном сервисе, агенту нужна интеграция с ним. Запись о встрече сама по себе не создаёт событие в календаре. Мне важно связать эти вещи и понимать, куда записывать и где обновлять информацию.

    Запросы здесь довольно бытовые: «что делать дальше?», «найди мои записи об этом», «сохрани идею рядом с проектом, к которому она относится». Агент с доступом к файловой системе умеет удивительно много по хозяйству. Файлам всё равно, что они не исходный код.

    Одна база на трёх устройствах

    Мне нужна одна база, которая синхронизируется между телефоном, рабочим компьютером и сервером. С телефона удобно быстро записать мысль или заглянуть в список дел. За компьютером — разобрать записи и поработать над проектом. На сервере с теми же файлами работает агент, даже когда рабочий компьютер выключен.

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

    Это и есть нужная мне graceful degradation: без связи временно недоступны синхронизация и удалённый помощник, но с самой базой можно продолжать работать. Джарвис может подождать; записать мысль мне нужно сейчас.

    На iCloud всё это споткнулось

    Для синхронизации Obsidian я пользовался iCloud. На моих iOS-устройствах он работал достаточно плохо, чтобы я перестал ему доверять.

    Linux упростил выбор. Мне нужна была надёжная локальная копия на Linux-машине, где агент мог бы читать и менять файлы. Надёжно встроить iCloud в эту схему у меня не получилось. Прелесть базы знаний заметно тускнеет, когда работу с ней приходится начинать с выяснения, приехала ли она вообще.

    Официальный Obsidian Sync мне тоже не подошёл. В Standard дают 1 ГБ, в Plus — 10 ГБ: для базы знаний, в которой я хочу хранить свои PDF, смехотворный объём. У Plus есть расширение до 100 ГБ, но я предпочёл собственное хранилище без привязки размера коллекции к тарифу.

    В итоге я выбрал Self-hosted LiveSync, плагин сообщества, и собственный CouchDB. Несмотря на похожие названия, это отдельная система синхронизации.

    Что где работает

    Для синхронизации у меня отдельный сервер с CouchDB. А само хранилище и агент живут на Linux-сервере, который стоит у меня дома на шкафу. Он радует меня своим видом и независимостью от облачного хостинга: эта часть системы работает на моём железе.

    Телефон и компьютер обмениваются изменениями через CouchDB. На Linux Obsidian с LiveSync синхронизирует локальные файлы, с которыми работает агент.

    У каждого устройства есть локальная копия хранилища. LiveSync замечает правки, отправляет их в CouchDB и получает чужие изменения. На сервере лежит внутреннее представление данных плагина, а не папка с Markdown-файлами.

    Устройствам не обязательно быть в сети одновременно. Рабочий компьютер может отправить изменение и выключиться до того, как подключится телефон. Без сети заметки остаются доступны, а синхронизация подождёт.

    Агент работает с локальными файлами на Linux. Когда он меняет заметку, запущенный Obsidian замечает правку, а LiveSync передаёт её остальным устройствам. Отдельная интеграция агента с CouchDB для этого не нужна.

    В моём сетапе содержимое синхронизируется со сквозным шифрованием. На устройствах файлы остаются читаемыми для Obsidian и агента. Если агент использует удалённую модель, выбранные для запроса данные отправляются её провайдеру: шифрование синхронизации эту границу не меняет.

    На телефоне есть одна неизбежная оговорка. iOS может приостановить Obsidian в фоне, поэтому после открытия приложение иногда догоняет изменения. Плагин работает внутри Obsidian и не превращает его в постоянно работающий фоновый сервис. Бесшовность для меня здесь в том, что я не таскаю файлы руками и не думаю, какой операционной системе они принадлежат.

    Linux-машине тоже нужен Obsidian

    CouchDB сам по себе не создаёт на Linux папку с заметками. Кто-то должен превращать данные синхронизации обратно в файлы и подхватывать правки агента. У меня этим занимается тот же Obsidian с LiveSync, что и на рабочем компьютере.

    Только на сервере нет рабочего стола. Поэтому Obsidian запускается под Xvfb — виртуальным дисплеем. Приложение по-прежнему рисует своё окно, просто никто на него не смотрит. За запуском при загрузке машины и перезапуском после сбоя следит systemd. Держать открытой пользовательскую сессию не приходится.

    У этого экземпляра свой постоянный профиль: при старте он открывает нужное хранилище и загружает LiveSync. С новым профилем сервис вместо этого исправно показывал бы никому не видимый экран приветствия. А в подготовленном профиле ещё и разрешены сторонние плагины. Без этого установленный LiveSync останется выключенным: Obsidian работает, синхронизация — нет.

    Агент и Obsidian работают от разных пользователей, но оба могут читать и менять заметки. Общая группа и права на новые файлы нужны, чтобы созданная агентом запись оставалась доступна Obsidian. При этом каталог настроек .obsidian от агента закрыт: там код плагинов и состояние синхронизации, с которыми ему незачем работать.

    Git стоит рядом

    Ошибки синхронизация тоже переносит. Удалённый абзац может исчезнуть на всех устройствах с безупречной надёжностью.

    Поэтому на Linux у меня отдельно сохраняется история в Git. Правка с телефона сначала приезжает через LiveSync и становится изменением обычного файла. Раз в пять минут отдельный процесс собирает добавленные, изменённые и удалённые файлы в коммит с отметкой времени. Если ничего не изменилось, коммита нет. Правки агента подхватывает тот же процесс: ему всё равно, кто изменил файл.

    Это снимки состояния, которое успело доехать до Linux. Удаление, сделанное и отменённое между двумя запусками, может вообще не оставить следа в истории. Зато можно посмотреть, каким был проект утром, или найти абзац до того, как помощник решил его «улучшить».

    Служебная часть Git вынесена за пределы хранилища. У Git рабочие файлы и каталог с историей могут жить отдельно: заметки остаются на месте, а коммиты, индекс и настройки репозитория лежат рядом. В корне синхронизируемой папки нет .git, поэтому LiveSync не может случайно начать возить между устройствами внутренности самого Git. Синхронизировать заметки и заодно синхронизировать состояние программы, которая хранит их историю, мне кажется лишним приключением.

    Заметки и вложения сохраняются в одном Git-репозитории, а настройки .obsidian — в другом, с более узким доступом. Агент видит историю заметок, но не историю настроек подключения. Просто закрыть от него текущую папку было бы недостаточно, если её содержимое можно прочитать в старом коммите.

    Процесс, который делает снимки, тоже ограничен в правах. Он может читать хранилище и записывать историю в два внешних репозитория, но сами заметки для него доступны только на чтение. Его задача — запомнить, что произошло. Возможность заодно что-нибудь поправить ему не нужна.

    История доступна агенту для сравнения версий и поиска потерянного текста. Восстановленный файл для LiveSync будет обычным новым изменением и разойдётся по устройствам тем же способом, что любая другая правка.

    Git здесь работает локально; обмен между устройствами по-прежнему целиком на LiveSync. Потерю самой Linux-машины такая история не переживёт без независимой резервной копии.

    Теперь можно заниматься более интересной частью: объяснять агенту, куда что складывать и что ему разрешено менять. По крайней мере, если я прошу что-то сохранить, результат уже можно открыть в Obsidian на телефоне.

    Ссылки

    • Obsidian — приложение для заметок и личной базы знаний.
    • Markdown — текстовый формат заметок.
    • PARA — описание подхода к организации информации от Тьяго Форте.
    • Obsidian Bases — встроенный плагин для представлений и коллекций заметок.
    • AGENTS.md — формат файла с инструкциями для агента.
    • iCloud — сервис, через который я раньше синхронизировал хранилище.
    • Obsidian Sync — официальный сервис синхронизации и его тарифы.
    • Self-hosted LiveSync — плагин, на котором работает моя синхронизация.
    • Apache CouchDB — база данных, через которую устройства обмениваются изменениями.
    • Xvfb — виртуальный дисплей для серверного Obsidian.
    • systemd — управление процессами и периодическими запусками на Linux.
    • Git — история изменений и возврат к предыдущим версиям.