Files
claude-skills/obsidian-memory/SKILL.md
T
creator 535f9e8cd0 feat: add obsidian-memory skill
Протокол работы 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-флаг
2026-04-19 12:54:54 +00:00

244 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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/
│ └── <slug>.md cumulative per-project context
├── insights/ dated observations: YYYY-MM-DD-<slug>.md
├── conversations/ session summaries: YYYY-MM-DD-<slug>.md
└── inbox/ drafts for user review
```
**Write rule:** Claude пишет *только* в `claude/**`. Всё остальное —
read-only. Если кажется что стоит дополнить `20-knowledge/…` — положить
в `claude/inbox/` с пометкой «proposed addition to <path>» и отдать
пользователю на ревью.
## Frontmatter
Каждый файл в `claude/**` начинается с YAML-frontmatter:
```yaml
---
type: memory | insight | conversation | fact | preference
project: <slug> # опционально; lotus-eletre, uspeak, и т.п.
tags: [<tag1>, <tag2>] # свободная форма, 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=<keyword>&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-<slug>.md` |
| Накопительный контекст по проекту (обновляется) | `claude/memory/projects/<slug>.md` |
| Стабильный факт общего характера | `claude/memory/facts.md` (append в секцию) |
| Предпочтение пользователя | `claude/memory/preferences.md` |
| Выжимка самой беседы | `claude/conversations/YYYY-MM-DD-<slug>.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":"<b64>"},
{"operation":"update", "path":"claude/memory/projects/…", "content":"<b64>", "sha":"<prev-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-<slug>.md` — slug kebab-case, ASCII
- `claude/conversations/YYYY-MM-DD-<slug>.md` — аналогично
- `claude/memory/projects/<slug>.md` — slug совпадает с
`10-projects/<slug>/` если проект существует
- `claude/memory/<topic>.md` — accumulating files (facts, preferences)
Русские названия → транслит или короткий англ. эквивалент.
`лотос-настройка-развала` → `lotus-alignment`.
## Boundaries
- **Не писать в пользовательские папки** (00–30). Если нужно предложить
изменение — в `claude/inbox/` с пометкой.
- **Не удалять пользовательские файлы никогда.** Свои (`claude/**`) —
можно, если очевидно устарело; предпочтительнее `private: true` чем
удаление (история сохраняется в git, но из выдачи исчезает).
- **Не обходить `private: true`.** Такие заметки не цитировать
и не упоминать.
- **Честно флагить противоречия** между тем что в vault и что говорит
пользователь, не исправляя молча.