--- name: obsidian-memory description: Protocol for using creator/obsidian-vault (Gitea repo at h3fq32.golive.ru) as Claude's long-term memory for personal and R&D projects of Arthur Abelentsev. Trigger when the user references past work ("my X project", "we decided Y", "remember that..."), asks Claude to remember/save/update/forget something, mentions a project by name (lotus-eletre, uspeak-trademark, homework-*, 1c-, pcb-*, obsidian, claude-skills), or whenever a substantive insight, decision, or fact surfaces that's worth preserving between sessions. Covers personal context, infrastructure (gitea/traefik/mikrotik/xray), embedded firmware, PCB design, 1C consulting for any client, R&D on UCN products (acoustics, firmware, algorithms), legal/trademark work, travel, vehicle/hardware, and general life. Also covers answering non-trivial project questions that benefit from previously stored context. Describes vault layout, frontmatter conventions, Gitea REST API mechanics (read/list/search/create/update), naming rules, and write permissions. Do NOT trigger for: simple one-off technical questions or casual chat that doesn't involve the user's ongoing projects. Do NOT trigger for UCN marketing/sales commercial work (clients, distributors, quotes, exhibitions, pricing, product marketing for uWave/Zima2/uSpeak) — that is handled by a separate ucnl-market-memory skill and a separate repo (ucnlmarket/ucnl-market-memory). --- # obsidian-memory Протокол работы с `creator/obsidian-vault` как долговременной памятью. Vault — обычный git-репо в Gitea, хранит markdown-заметки с YAML-frontmatter. Claude читает и пишет заметки через Gitea REST API. ## Разграничение доменов — прочитать первым У пользователя **два репо памяти** с жёстким разделением: | Домен | Репо | Скилл | |---|---|---| | Личные проекты Артура, инфраструктура, embedded, 1С-консалтинг (любые клиенты), R&D по UCN-продуктам, legal/trademark, быт | `creator/obsidian-vault` | **этот скилл** | | Маркетинг и продажи UCN (клиенты, дистрибьюторы, выставки, КП, экспорт, product marketing uWave/Zima2/uSpeak/USBL) | `ucnlmarket/ucnl-market-memory` | `ucnl-market-memory` | **Правило жёсткое:** материалы из одного домена НЕ попадают в репо другого. Если тема пограничная — спросить пользователя, не додумывать. **Примеры границы:** | Запрос | Куда | |---|---| | «Прошивка uWave — обновить через STM32CubeProg» | R&D → **этот скилл** | | «Письмо Mavi Marine по срокам поставки» | sales UCN → `ucnl-market-memory` | | «Расчёт TDOA для uWave USBL» | R&D/алгоритмы → **этот скилл** | | «Слайд для INNOPROM KSA 2026» | маркетинг UCN → `ucnl-market-memory` | | «ТЗ на 1С для Teplovin» | 1С не-UCN → **этот скилл** | | «Скидка дистрибьютору X» | sales UCN → `ucnl-market-memory` | «UCN как клиент внутреннего 1С-проекта» — дефолт этот скилл (технический слой), но с коммерческой частью (бюджет, контракт) — уточнить. ## Where things live - **Gitea:** `https://git.h3fq32.golive.ru` - **Repo:** `creator/obsidian-vault` - **Branch:** `main` - **Access:** `bash_tool` + `curl` с `Authorization: token $GITEA_TOKEN` Токен должен быть в окружении (`$GITEA_TOKEN`) или в сессионном контексте. Если ни там, ни там его нет — попросить пользователя один раз в начале, в последующих вызовах использовать. ## Vault layout ``` 00-inbox/ user's raw notes, READ-ONLY for Claude 10-projects/ active projects (lotus-eletre/, uspeak/, …), READ-ONLY 20-knowledge/ reference (1c/, embedded/, infrastructure/), READ-ONLY 30-daily/ daily log, meetings, READ-ONLY claude/ Claude's own space, READ-WRITE ├── memory/ │ ├── facts.md stable facts (one file, append-only section) │ ├── preferences.md user preferences and standards │ ├── projects/ │ │ └── .md cumulative per-project context │ └── 1c/ отдельная область: 1С-экосистема пользователя │ ├── README.md протокол + конвенции именно для 1С │ ├── configurations/ КА, ERP, УТ, ЗУП — по конфигурациям │ ├── projects/ клиентские 1С-внедрения │ └── files/ шаблоны и эталонные документы │ ├── README.md │ └── list.md реестр: имя файла ↔ описание ├── insights/ dated observations: YYYY-MM-DD-.md ├── conversations/ session summaries: YYYY-MM-DD-.md └── inbox/ drafts for user review ``` **Areas vs projects:** `claude/memory/projects/` — разовый контекст одного проекта в одном файле. `claude/memory//` — целая тематическая область со своей подструктурой. Сейчас такая есть одна (`1c/`), могут появиться ещё (`embedded/`, `infrastructure/` если разрастётся из `facts.md`). Решение «один файл vs целая папка» принимается по тому, нужна ли внутренняя структура (конфигурации, клиенты, паттерны) — если да, это область. ### 1С — special case В начале любого разговора, где всплывают 1С-темы (конфигурации КА/ERP/УТ/ЗУП, внедрения, BSL-код, интеграции с Bitrix24, ТЗ на 1С-проекты): 1. Прочитать `claude/memory/1c/README.md` — там протокол 2. Листинг `configurations/` и `projects/` — увидеть актуальный набор 3. Прицельно 2–3 релевантных файла 4. Параллельно — skill `1c-analyst` для процедурных знаний (как делать); vault — для «что у пользователя конкретно есть и как» **Если запрос подразумевает генерацию документа** (приказ, ТЗ, регламент, проектная документация, типовое письмо) — дополнительно: 5. Прочитать `claude/memory/1c/files/list.md` — это реестр шаблонов 6. Если в таблице есть подходящий по смыслу шаблон — скачать файл через Gitea raw-endpoint, открыть через соответствующий skill (`docx`/`xlsx`/`pdf-reading`), использовать как основу 7. Если подходящего шаблона нет — сгенерировать с нуля, в конце предложить пользователю сохранить результат в `files/` как новый шаблон (тогда одним коммитом: файл + строка в `list.md`) **Важно:** файл в `files/` без строки в `list.md` для Claude не существует. При любом добавлении/обновлении — реестр дописывается. **Write rule:** Claude пишет *только* в `claude/**`. Всё остальное — read-only. Если кажется что стоит дополнить `20-knowledge/…` — положить в `claude/inbox/` с пометкой «proposed addition to » и отдать пользователю на ревью. ## Frontmatter Каждый файл в `claude/**` начинается с YAML-frontmatter: ```yaml --- type: memory | insight | conversation | fact | preference project: # опционально; lotus-eletre, uspeak, и т.п. tags: [, ] # свободная форма, kebab-case created: YYYY-MM-DD updated: YYYY-MM-DD relevance: 0.0-1.0 # оценка важности, используется при ранжировании confidence: low | medium | high private: false # true → не использовать в ответах, не упоминать наличие sources: # опционально: откуда знание пришло - conversation: 2026-04-19-lotus-yaw-calibration - url: https://… --- ``` `private: true` — сильное правило. Такие заметки читать можно (для понимания контекста пользователя), но в ответах не цитировать, не ссылаться, и не упоминать факт их существования. ## Protocol ### 1. В начале содержательного разговора Если разговор касается проекта/системы/темы, по которым у пользователя может быть накопленный контекст: 1. **Проверить домен.** Если это маркетинг/продажи UCN — СТОП, переключиться на `ucnl-market-memory` skill. 2. **Поиск по теме.** Content-поиск по vault через API: ``` GET /api/v1/repos/creator/obsidian-vault/search?q=&type=code ``` Альтернатива для поиска по frontmatter-полю — grep по всем файлам в `claude/memory/projects/`: ``` GET /api/v1/repos/creator/obsidian-vault/contents/claude/memory/projects ``` 3. **Читаем top-3..5 самых релевантных.** Приоритет: свежесть (`updated`), явный `project` match, высокий `relevance`. Исключить `private: true` из ответов (но прочитать можно). 4. **Использовать контекст** в ответе естественно, без меты про «я нашёл заметку...». ### 2. Когда НЕ искать - Простые технические вопросы без персонального контекста («как в Python отсортировать список по ключу») - Разговорная болтовня, приветствия - Одноразовые операции - Вопросы, где пользователь сам дал весь нужный контекст в сообщении - Темы маркетинга/продаж UCN — это не сюда ### 3. В процессе разговора - При упоминании сущностей, имеющих свою заметку в vault, использовать `[[wiki-links]]` в новых заметках (пригодится для навигации в Obsidian) - Если обнаружилось противоречие между памятью и тем что говорит пользователь сейчас — честно сказать («в заметках было X, сейчас Y — обновить?»), не тихо исправлять ### 4. В конце содержательного разговора Если всплыли значимые инсайты / факты / решения — сохранить: | Что появилось | Куда класть | |---|---| | Одноразовое наблюдение по проекту | `claude/insights/YYYY-MM-DD-.md` | | Накопительный контекст по проекту (обновляется) | `claude/memory/projects/.md` | | Стабильный факт общего характера | `claude/memory/facts.md` (append в секцию) | | Предпочтение пользователя | `claude/memory/preferences.md` | | Выжимка самой беседы | `claude/conversations/YYYY-MM-DD-.md` | | Сомневаешься куда — | `claude/inbox/` + explicit note пользователю | **Не писать ради галочки.** Лучше 0 файлов, чем пять пустословных. Критерий: «если через полгода другой instance Claude прочитает эту заметку — она ему что-то даст?». ## Gitea REST API — шпаргалка ```bash GITEA=https://git.h3fq32.golive.ru REPO=creator/obsidian-vault TOKEN=$GITEA_TOKEN # или подставить вручную # ── READ ──────────────────────────────────────────────────────────────────── # Прочитать файл (raw содержимое) curl -sS -H "Authorization: token $TOKEN" \ "$GITEA/api/v1/repos/$REPO/raw/claude/memory/facts.md" # Листинг папки (metadata всех файлов) curl -sS -H "Authorization: token $TOKEN" \ "$GITEA/api/v1/repos/$REPO/contents/claude/memory/projects?ref=main" \ | python3 -c "import sys,json; [print(x['path'], x['size']) for x in json.load(sys.stdin)]" # Content-поиск (требует включённый индекс на уровне инстанса Gitea) curl -sS -H "Authorization: token $TOKEN" \ "$GITEA/api/v1/repos/$REPO/search?q=eletre+alignment&type=code" # Tree (вся структура целиком с recursive) curl -sS -H "Authorization: token $TOKEN" \ "$GITEA/api/v1/repos/$REPO/git/trees/main?recursive=true" # ── WRITE ─────────────────────────────────────────────────────────────────── # Создать новый файл (POST contents). Содержимое — base64. content_b64=$(base64 -w0 /tmp/note.md) curl -sS -X POST -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ "$GITEA/api/v1/repos/$REPO/contents/claude/insights/2026-04-19-foo.md" \ -d "{ \"message\": \"claude: insight on X\", \"content\": \"$content_b64\", \"branch\": \"main\" }" # Обновить существующий файл (PUT, нужен sha текущей версии) sha=$(curl -sS -H "Authorization: token $TOKEN" \ "$GITEA/api/v1/repos/$REPO/contents/claude/memory/facts.md?ref=main" \ | python3 -c "import sys,json; print(json.load(sys.stdin)['sha'])") content_b64=$(base64 -w0 /tmp/facts-new.md) curl -sS -X PUT -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ "$GITEA/api/v1/repos/$REPO/contents/claude/memory/facts.md" \ -d "{ \"message\": \"claude: update facts — add Eletre calibration notes\", \"content\": \"$content_b64\", \"sha\": \"$sha\", \"branch\": \"main\" }" # Batch (несколько файлов одним коммитом) — POST contents БЕЗ пути curl -sS -X POST -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ "$GITEA/api/v1/repos/$REPO/contents" \ -d '{ "branch": "main", "message": "claude: session summary with 2 artefacts", "files": [ {"operation":"create", "path":"claude/conversations/…", "content":""}, {"operation":"update", "path":"claude/memory/projects/…", "content":"", "sha":""} ] }' ``` ## Gotchas (learned the hard way) 1. **`content`, не `content_base64`.** В `POST /contents` (включая batch) поле называется `content`. Если послать `content_base64` — Gitea тихо проигнорирует неизвестный ключ и создаст файл нулевого размера. Файл «появится», коммит пройдёт, а содержимое будет пустое. 2. **URL-encode путей.** Папки с пробелами/кириллицей → encode перед API-вызовом: `curl "…/contents/30-daily/2026-04-19%20%D0%B4%D1%8Bнь.md"`. 3. **`PUT` требует `sha` текущей версии.** Забыл sha — получишь 409. Всегда перечитывать перед update'ом. 4. **Новый репо «пустой» после `auto_init=true`.** Первый commit через API создаёт initial commit и ветку main. До этого момента API `?ref=main` возвращает 404. 5. **Rate limit.** По умолчанию Gitea не агрессивен, но batch-операции предпочтительнее N одиночных запросов — один коммит лучше для истории и дешевле по HTTP. ## Commit message format Все коммиты Claude в vault — префикс `claude:`: - `claude: save <тема> from conversation` — новая заметка - `claude: update <путь> — <что именно>` — правка - `claude: merge <откуда> → <куда>` — переорганизация - `claude: remove <путь> — <причина>` (редко; чаще `private: true`) Это позволяет пользователю легко фильтровать `git log | grep ^claude:` и понять что делал Claude в vault. ## Naming - `claude/insights/YYYY-MM-DD-.md` — slug kebab-case, ASCII - `claude/conversations/YYYY-MM-DD-.md` — аналогично - `claude/memory/projects/.md` — slug совпадает с `10-projects//` если проект существует - `claude/memory/.md` — accumulating files (facts, preferences) Русские названия → транслит или короткий англ. эквивалент. `лотос-настройка-развала` → `lotus-alignment`. ## Boundaries - **Не писать в пользовательские папки** (00–30). Если нужно предложить изменение — в `claude/inbox/` с пометкой. - **Не удалять пользовательские файлы никогда.** Свои (`claude/**`) — можно, если очевидно устарело; предпочтительнее `private: true` чем удаление (история сохраняется в git, но из выдачи исчезает). - **Не обходить `private: true`.** Такие заметки не цитировать и не упоминать. - **Честно флагить противоречия** между тем что в vault и что говорит пользователь, не исправляя молча. - **Не писать в `ucnlmarket/ucnl-market-memory` из этого контекста.** Если тема всплыла UCN-sales — переключиться на `ucnl-market-memory` skill.