From 535f9e8cd053bd3130a1d6c0b2467488d3bbdf94 Mon Sep 17 00:00:00 2001 From: creator Date: Sun, 19 Apr 2026 12:54:54 +0000 Subject: [PATCH] feat: add obsidian-memory skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Протокол работы Claude с creator/obsidian-vault как долговременной памятью через Gitea REST API. Покрывает: - структуру vault (claude/** — RW, остальное RO) - frontmatter-конвенции (type, project, tags, created/updated, relevance, confidence, private) - протокол: когда искать, что читать, куда писать, что НЕ делать - Gitea REST API шпаргалка (read/list/search/create/update/batch) - gotchas trial-and-error (поле 'content' а не 'content_base64', URL-encode путей, sha для PUT) - формат коммит-сообщений (claude: …) - правила именования, boundaries, private-флаг --- README.md | 3 + obsidian-memory/SKILL.md | 243 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 obsidian-memory/SKILL.md diff --git a/README.md b/README.md index 4a1edce..0f1c7b3 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Custom skills for Claude.ai (claude.ai → Settings → Skills). | **bulletproof** | 12-stage adaptive dev workflow (research → deploy). Adapted for Python/Docker/Traefik/MikroTik/embedded stacks, Gitea CI/CD, SonarQube. Based on Bulletproof v5.0 by Artemiy Miller. | | **embedded-firmware-engineer** | Bare-metal & RTOS firmware: ESP32/ESP-IDF, STM32 HAL/LL, Nordic nRF, FreeRTOS, Zephyr. NASA/JPL Power of Ten rules, banned functions, DMA/cache coherence, GPIO policy, watchdog strategy, brown-out testing. | | **my-python-senior** | Senior-level Python engineer for systems, containers, LLM workflows, networking, and file processing. | +| **obsidian-memory** | Protocol for using `creator/obsidian-vault` (Gitea repo) as Claude's long-term memory. Vault layout, frontmatter conventions, Gitea REST API mechanics, write-permission boundaries. | | **pcb-ai-engineer** | Code-driven schematic & PCB design using Circuit-Synth (Python) → KiCad → Altium. Universal STM-family abstraction with `family → package → pinmap → capabilities` data model. | ## Structure @@ -34,6 +35,8 @@ claude-skills/ │ ├── files-io.md │ ├── networking.md │ └── systems.md +├── obsidian-memory/ +│ └── SKILL.md └── pcb-ai-engineer/ ├── SKILL.md ├── main.py diff --git a/obsidian-memory/SKILL.md b/obsidian-memory/SKILL.md new file mode 100644 index 0000000..afd7a0d --- /dev/null +++ b/obsidian-memory/SKILL.md @@ -0,0 +1,243 @@ +--- +name: obsidian-memory +description: Protocol for using creator/obsidian-vault (Gitea repo at h3fq32.golive.ru) as Claude's long-term memory. 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, homework-*, 1c-*, pcb-*, obsidian, claude-skills), or whenever a substantive insight, decision, or fact surfaces that's worth preserving between sessions. 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 or personal context. +--- + +# obsidian-memory + +Протокол работы с `creator/obsidian-vault` как долговременной памятью. +Vault — обычный git-репо в Gitea, хранит markdown-заметки с YAML-frontmatter. +Claude читает и пишет заметки через Gitea REST API. + +## 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 +├── insights/ dated observations: YYYY-MM-DD-.md +├── conversations/ session summaries: YYYY-MM-DD-.md +└── inbox/ drafts for user review +``` + +**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. **Поиск по теме.** 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 + ``` +2. **Читаем top-3..5 самых релевантных.** Приоритет: свежесть (`updated`), + явный `project` match, высокий `relevance`. Исключить `private: true` + из ответов (но прочитать можно). +3. **Использовать контекст** в ответе естественно, без меты про «я + нашёл заметку...». + +### 2. Когда НЕ искать + +- Простые технические вопросы без персонального контекста + («как в Python отсортировать список по ключу») +- Разговорная болтовня, приветствия +- Одноразовые операции +- Вопросы, где пользователь сам дал весь нужный контекст в сообщении + +### 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 и что говорит + пользователь, не исправляя молча.