
Obsidian Project Memory
- 1 installs
- 3.2k repo stars
- Updated August 4, 2026
- brycewang-stanford/awesome-agent-skills-for-empirical-research
obsidian-project-memory is a skill that maintains a filesystem-first, agent-driven Obsidian knowledge base for a research project without requiring MCP.
About
This skill maintains a filesystem-first, agent-driven Obsidian knowledge base for a research project. A researcher uses it to detect and bind a repo, read minimum context, classify a knowledge delta, and write durable notes across papers, experiments, results, and writing without MCP or API keys. It matters as the main authority for keeping research project memory synchronized and durable.
- Maintains a filesystem-first, agent-driven Obsidian research knowledge base
- Classifies each turn into knowledge, paper, experiment, result, or writing buckets
- Uses scripts for state and agents for synthesis, no MCP or API keys required
Obsidian Project Memory by the numbers
- 1 all-time installs (skills.sh)
- Ranked #2,479 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
obsidian-project-memory capabilities & compatibility
- Capabilities
- project memory · knowledge base setup · research synthesis
- Works with
- obsidian
- Use cases
- research · project management · documentation
- Pricing
- Free
What obsidian-project-memory says it does
Maintain a **filesystem-first, agent-driven** Obsidian knowledge base for a research project.
Do **not** require MCP, API keys, REST plugins, or `.base` artifacts.
npx skills add https://github.com/brycewang-stanford/awesome-agent-skills-for-empirical-research --skill obsidian-project-memoryAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 3.2k |
| Last updated | August 4, 2026 |
| Repository | brycewang-stanford/awesome-agent-skills-for-empirical-research ↗ |
What it does
Maintain and synchronize a filesystem-first Obsidian research knowledge base with durable, routed project notes.
Who is it for?
Keeping research project memory, daily notes, experiments, results, and writing synchronized in a compact Obsidian vault.
Skip if: Workflows that require MCP, API keys, REST plugins, or .base artifacts.
When should I use this skill?
When the user asks to maintain an Obsidian knowledge base for a research project or keep project memory and daily notes synchronized.
What you get
Durable notes routed to the correct vault folders plus updated hub, daily, and project-memory files.
- Durable notes across Knowledge, Papers, Experiments, Results, and Writing
- Updated Daily and project-memory notes
By the numbers
- 7 knowledge-delta buckets
- 6-step default workflow
Files
Obsidian Project Memory
Maintain a filesystem-first, agent-driven Obsidian knowledge base for a research project.
Default note output language follows the project's configured note_language; if no note language is configured, default to English. Keep technical terms, paper titles, and established folder names in their original form when that is clearer. Only switch note prose to another language when the user explicitly asks.
Prefer this skill when working inside a repository that:
- already contains
.claude/project-memory/registry.yaml, or - clearly looks like a research project and should be bound to an Obsidian vault.
Core principles
- Use scripts for project state management.
- Use agents for project understanding and synthesis.
- Write only durable research knowledge into a small vault structure.
- Do not require MCP, API keys, REST plugins, or
.baseartifacts. - Do not depend on
.canvasglobally, but allow literature workflows to maintainMaps/literature.canvasas a default literature graph artifact. - Treat internal experiment summary reports as durable result-facing notes under
Results/Reports/, not asWriting/notes.
Default vault structure
Write into this project layout only:
Research/{project-slug}/
00-Hub.md
01-Plan.md
Knowledge/
Papers/
Experiments/
Results/
Reports/
Writing/
Daily/
Archive/Read references/SCHEMA.md for the exact structure and note roles.
Deterministic helper script
Use scripts/project_kb.py only for low-freedom operations such as detect, bootstrap, sync, and lifecycle management:
python3 scripts/project_kb.py detect --cwd "$PWD"
python3 scripts/project_kb.py bootstrap --cwd "$PWD" --vault-path "$OBSIDIAN_VAULT_PATH"
python3 scripts/project_kb.py sync --cwd "$PWD" --scope auto
python3 scripts/project_kb.py lifecycle --cwd "$PWD" --mode archive
python3 scripts/project_kb.py query-context --cwd "$PWD" --kind broad
python3 scripts/project_kb.py query-context --cwd "$PWD" --kind experiment --query freezing
python3 scripts/project_kb.py find-canonical-note --cwd "$PWD" --kind experiment --query freezing
python3 scripts/project_kb.py note-lifecycle --cwd "$PWD" --mode archive --note "Results/Old-Result.md"Do not expect the script to understand project meaning. It manages state; it does not replace synthesis.
Read references/SCRIPT-VS-AGENT.md when deciding whether a task belongs in the script or must stay agent-driven.
Default workflow
1. Detect and bind
1. Run scripts/project_kb.py detect --cwd "$PWD". 2. If the repo is already bound, continue with the existing project. 3. If the repo is not yet bound but is a strong research-project candidate, bootstrap it with project_kb.py bootstrap.
For the detailed lifecycle, read references/WORKFLOW.md.
2. Read the minimum context
Before writing anything, read only the minimum stable context:
.claude/project-memory/<project_id>.md00-Hub.md01-Plan.md- today's
Daily/YYYY-MM-DD.mdif it exists
If the task is about project understanding, existing docs, or historical results, load more context selectively using the references below.
3. Classify the knowledge delta
Route the current turn into one or more of these buckets:
knowledgepaperexperimentresultwritingdailyproject-structure
Read references/NOTE-ROUTING.md before writing.
4. Follow the default durable research path
Default path for substantive research work:
Papers/-> extract reusable ideas, baselines, and project relevanceExperiments/-> turn those into testable hypotheses, runbooks, or ablationsResults/-> promote stable findings with evidence and interpretationResults/Reports/-> store one round or one batch's internal experiment report when a complete retrospective has been writtenWriting/-> externalize durable claims into reviews, proposals, drafts, slides, or rebuttal notes
Use Daily/ as chronology and staging, not the final home for durable research knowledge.
Read references/PAPERS-TO-WRITING.md when deciding how a turn should advance along this path.
5. Decide whether agent-first synthesis is required
Use agent-first import/synthesis when:
- importing an existing repository for the first time,
- the user says the knowledge base is empty or lacks background,
- multiple source documents must be synthesized into stable project knowledge,
- the project needs a durable overview, research questions, experiment map, or results summary.
In these cases, first use an agent to read key sources, then write the synthesized result back into Obsidian.
Read references/AGENT-FIRST-IMPORT.md for the recommended source-reading order.
6. Write back minimally
Always keep write-back conservative.
Write back at least:
- today's
Daily/YYYY-MM-DD.mdwhen this turn changes project state, 00-Hub.mdonly when recent progress or top-level status truly changes,.claude/project-memory/<project_id>.mdwhen project state changes.
Then write only the durable note that matches the bucket:
knowledge->Knowledge/paper->Papers/experiment->Experiments/result->Results/writing->Writing/daily->Daily/project-structure-> usuallyKnowledge/Project-Overview.mdorKnowledge/Source-Inventory.md
Internal experiment round reports should default to:
Results/Reports/YYYY-MM-DD--{experiment-line}--r{round}--{purpose}.md
Read references/NOTE-TEMPLATES.md when a note needs a stable shape.
Knowledge CRUD rules
Treat the vault as a small set of canonical notes plus supporting daily context.
Create
- Ingest new knowledge deliberately; do not equate every new Markdown file with a durable note.
- Keep one canonical note per durable object whenever possible:
- one stable project overview,
- one stable experiment note per experiment line,
- one stable result note per durable finding,
- one stable paper note per paper.
- For new Markdown files, default to summarize first, then route:
- promote directly only when the file is already stable and self-contained,
- otherwise merge into an existing canonical note or stage it in
Daily/. - If the new durable object is a full internal experiment report, store it under
Results/Reports/and link the matchingExperiments/and canonicalResults/notes.
Read
- Query narrowly first:
- broad project questions ->
00-Hub.md+ keyKnowledge/notes, - active work questions ->
01-Plan.md+ today'sDaily/+ project memory, - specific experiment/result/paper questions -> the matching canonical note first,
- specific internal experiment retrospective -> the matching note in
Results/Reports/first. - Use agent synthesis only when the answer spans multiple durable sources or still depends on repo material after reading canonical notes.
Update
- Prefer updating an existing canonical note over creating a sibling note.
- Treat raw material as input, not as a final vault object.
- Allow fast append-only logging in
Daily/, but keep durable knowledge inKnowledge/,Papers/,Experiments/,Results/,Results/Reports/, orWriting/.
Delete
- Treat “remove”, “delete”, or “stop using” as archive by default.
- Purge only when the user explicitly asks for permanent deletion.
- When archiving or purging a durable note, repair direct links in
00-Hub.md,01-Plan.md, and explicit index notes so the main working surface does not point to missing files.
Safety rules
- Do not mirror the whole repository into the vault.
- Do not generate empty folder taxonomies or placeholder notes without real content.
- Do not write every repo delta into a new note.
- Do not treat every code change as a knowledge update.
- Do not create
.basefiles unless the user explicitly asks for them. - Do not create arbitrary
.canvassprawl; the main default exception isMaps/literature.canvasfor literature workflows. - For engineering-only turns, prefer
Daily/plus project memory unless there is a real experiment, result, or planning impact. - Treat “remove project knowledge” as archive by default; purge only when the user explicitly asks for permanent deletion.
Reference files
Load only what is needed:
references/SCHEMA.md- vault structure and note rolesreferences/WORKFLOW.md- detect/bootstrap/sync/archive workflowreferences/PAPERS-TO-WRITING.md- default handoff from literature to experiments, results, and writingreferences/SCRIPT-VS-AGENT.md- boundary between low-freedom script operations and agent-only reasoningreferences/KNOWLEDGE-CRUD.md- create/read/update/delete rules for durable research knowledgereferences/NOTE-ROUTING.md- where each kind of knowledge should goreferences/NEW-MD-INGESTION.md- how to ingest a newly created Markdown filereferences/AGENT-FIRST-IMPORT.md- how to import an existing project with agent synthesisreferences/NOTE-TEMPLATES.md- lightweight note shapes for common note types
Agent-First Import
When to use this workflow
Use agent-first import when:
- a repository already contains substantial project documents,
- the user says the knowledge base lacks background,
- multiple sources must be combined into a stable project summary,
- the project needs a real overview instead of a folder skeleton.
Recommended source-reading order
Read only the most informative sources first:
1. README.md if it is meaningful 2. plan/ or docs/ design notes 3. outputs/analysis/ reports and summaries 4. run/conf/ for task protocol and experimental assumptions 5. src/analysis_module/ or other orchestration code for analysis modes 6. TODO.md or scratch notes only as supplemental context
What the agent should extract
Ask the agent to produce these sections: 1. project background and research goal 2. core research questions 3. current main experiment lines 4. key results and conclusions 5. codebase-to-knowledge-base mapping 6. recommended durable notes to create or update 7. top content for 00-Hub.md
After the agent returns
Do not paste the entire agent response into the vault.
Instead:
- convert the synthesis into durable notes,
- keep one idea per note,
- put high-level framing in
Knowledge/, - put experiment logic in
Experiments/, - put findings in
Results/, - put literature-facing material in
Papers/.
Anti-pattern
Do not treat file paths as meaning.
Examples of bad behavior:
- mapping every
plan/*.mdfile into a one-to-one note automatically, - generating empty notes because a folder exists,
- creating new notes before understanding which sources matter.
Knowledge CRUD
Use these rules when maintaining a research-project knowledge base.
Core defaults
- One canonical note per durable object
- Prefer updating over duplicating
- Raw material is not durable knowledge
- Archive by default; purge only on explicit request
- Query narrowly first, synthesize second
Default research progression
When a research turn is substantive, prefer moving durable knowledge forward along this path:
Papers -> Experiments -> Results -> WritingInterpretation:
- a paper note should often end with a testable takeaway, not only a summary,
- an experiment note should clarify what evidence would justify a result note,
- a result note should usually clarify what writing object should absorb the claim next.
This progression does not mean every turn must touch all four folders. It means the next durable handoff should be made explicit whenever it is already clear.
Create
When new knowledge appears, answer two questions first:
1. Which type is it?
knowledgepaperexperimentresultwritingdaily
2. Is it a durable note or raw material?
Default policy: summarize first, then route.
Promote directly only when the content is already:
- self-contained,
- stable,
- clearly bounded,
- likely to be referenced later.
Otherwise:
- merge it into the existing canonical note for the same object, or
- stage it in
Daily/if it is not stable enough yet.
Never:
- map new files one-to-one into new durable notes by path alone,
- create a new canonical note for the same experiment/result/paper without a real distinction,
- turn every discovered Markdown file into a formal vault object.
Read
Use the smallest sufficient read set first.
Query presets
- broad project question ->
00-Hub.md+Knowledge/Project-Overview.md+Knowledge/Research-Questions.md - next step / active work ->
01-Plan.md+ today'sDaily/+ project memory - specific experiment -> matching note in
Experiments/ - specific result -> matching note in
Results/ - literature question -> matching note in
Papers/
Query order
1. canonical note 2. neighboring durable notes 3. daily or scratch context 4. repo source docs or outputs 5. agent synthesis
Do not start by scanning the entire vault or repo when a canonical note already exists.
Update
When new material overlaps an existing durable object:
- update the canonical note,
- do not create a sibling note by default.
Update style by folder:
Knowledge/-> rewrite stable conclusions; avoid timestamp noiseExperiments/-> preserve experiment identity; add updates, findings, next stepsResults/-> update headline, evidence, interpretationWriting/-> continue draft evolution or split by output object when necessaryDaily/-> append freely; later promote durable parts
Merge and split rules:
- merge several small notes when they are clearly about one durable object,
- split a note when it has grown into multiple durable objects with different lifecycles.
Delete
Interpret deletion intent carefully:
- “remove / delete / stop using / no longer needed” -> archive
- “keep history but stop using” -> archive
- “permanently delete / purge” -> purge
Archive
Default action:
- move the target note into
Archive/, - repair direct links in
00-Hub.md,01-Plan.md, and explicit index notes, - avoid leaving the main working surface with broken links.
Purge
Only on explicit permanent-delete intent:
- delete the target note,
- clean direct links in
00-Hub.md,01-Plan.md, and explicit index notes, - ensure the deleted note was not the only canonical carrier of still-needed knowledge.
Rename or move
Treat rename or move as:
- update of the same durable object, plus
- link repair
Do not treat rename as delete-plus-create unless the object meaning actually changed.
New Markdown Ingestion
Use this guide when a new Markdown file appears and should be considered for the knowledge base.
Three-step decision
1. Classify
Classify the file as one of:
knowledgepaperexperimentresultwritingdaily
2. Decide: durable note or raw material
Treat it as a durable note only if it is already:
- complete enough to stand on its own,
- stable in scope,
- likely to be referenced later.
Otherwise treat it as raw material.
3. Choose the action
Choose one of these:
- promote
- use only when the file is already a stable, complete, long-lived note
- merge
- use when it supplements an existing canonical note for the same object
- stage-to-daily
- use when it is still unstable, incomplete, or not worth promoting yet
Default answer: summarize first, then route.
Examples
New paper summary
- likely classification:
paper - if complete and stable -> promote to
Papers/ - if partial reading notes for an existing paper note -> merge
New experiment plan
- likely classification:
experiment - if it defines a distinct experiment line -> promote to
Experiments/ - if it refines an existing experiment -> merge into that note
New result memo
- likely classification:
result - if it contains a durable conclusion with evidence -> promote to
Results/ - if it is a full internal experiment summary report -> promote to
Results/Reports/using the stable naming contract - if it is still exploratory -> stage in
Daily/or merge into the existing experiment note first
New meeting note
- likely classification:
daily - default -> stage in
Daily/ - promote only if the meeting produced a stable decision that belongs in
Knowledge/,Experiments/, orWriting/
New scratch idea
- likely classification:
dailyorknowledge - default -> stage in
Daily/ - promote later only if it becomes a stable research question, method direction, or experiment plan
Cross-stage routing hint
When a new file is about papers, experiments, results, or writing, do not stop at file classification alone. Also ask whether it clearly implies the next durable handoff:
- paper note -> should an experiment note be updated?
- experiment note -> is there already a stable finding that belongs in
Results/? - result memo -> does a writing note need an update?
If that next handoff is already clear, prefer updating the downstream canonical note in the same turn.
Note Routing
First decide: durable note or raw material
Durable note
Treat content as a durable note when it is:
- likely to be referenced again after days or weeks,
- about a clearly bounded object,
- already stable enough to stand on its own,
- suitable to become the canonical note for that object.
Raw material
Treat content as raw material when it is:
- a short-lived intermediate artifact,
- a draft, memo, scratch note, or meeting fragment,
- an unverified analysis dump,
- incomplete support for a note that already exists.
Default rule: raw material should be summarized before promotion.
Route by knowledge type
Knowledge
Write to Knowledge/ when the content is stable and explanatory:
- project background
- research questions
- dataset protocol
- method landscape
- source inventory
- codebase overview
Do not put these here by default:
- temporary ideas,
- unverified hypotheses with no stable framing,
- daily execution logs.
Papers
Write to Papers/ when the content is primarily literature-facing:
- single paper notes
- related-work summaries
- paper-to-project relevance notes
- reading notes and literature synthesis
Do not put these here by default:
- project-only summaries with no literature object,
- raw meeting notes about papers,
- unrelated implementation notes.
Experiments
Write to Experiments/ when the content is about what was run or will be run:
- experiment design
- runbook
- ablation
- baseline comparison setup
- freezing / transfer / screening study
Do not put these here by default:
- raw metric dumps with no interpretation,
- broad project framing,
- final cross-experiment claims that belong in
Results/.
Results
Write to Results/ when the content captures a durable finding:
- final comparison
- mechanism conclusion
- collapse diagnosis
- figure and csv index
- cross-experiment interpretation
- stable canonical claim that should survive beyond one report
Do not put these here by default:
- unprocessed analysis output,
- notes that merely restate the experiment setup,
- temporary result speculation that still belongs in
Daily/.
Results Reports
Write to Results/Reports/ when the content is a complete internal experiment summary report:
- one experiment round retrospective,
- one batch report for a coherent experiment line,
- one decision-oriented wrap-up note backed by analysis artifacts.
These notes should use the naming contract:
YYYY-MM-DD--{experiment-line}--r{round}--{purpose}.md
Do not put these here by default:
- manuscript-facing draft text,
- raw metric dumps,
- vague summaries without one date / line / round / purpose.
Writing
Write to Writing/ when the content is meant for external output:
- paper draft fragments
- slide narrative
- rebuttal notes
- proposal text
Internal experiment reports do not belong here unless they are already external-facing writing artifacts.
Daily
Write to Daily/ when the content is transient or process-oriented:
- what happened today
- short sync queue
- quick scratch ideas
- temporary planning fragments
- lightweight meeting notes
Do not let Daily/ become the long-term home for canonical project knowledge. Promote durable content later.
Main routing rule
If a note will still matter after several days or weeks, prefer Knowledge/, Experiments/, Results/, Results/Reports/, Papers/, or Writing/.
If the note is mainly about today's progress or temporary organization, prefer Daily/.
Cross-folder promotion defaults
Treat these folders as a research pipeline, not as independent buckets:
Papers/should usually answer: what should we test, compare, or borrow?Experiments/should usually answer: what exactly are we running, and what finding would matter?Results/should usually answer: what do we now believe, with evidence?Results/Reports/should usually answer: what happened in this round or batch, and what decision does it imply?Writing/should usually answer: what should be said externally because of those results?
Default promotion path:
- paper insight -> experiment note
- stable experiment finding -> result note
- coherent round/batch retrospective -> results report note
- durable result claim -> writing note
If a turn reaches only one stage, keep it there. But when the next stage is already clear, prefer updating the next canonical note instead of leaving the chain broken.
Note Templates
Templates should follow the project's configured note_language; if no note language is configured, default to English.
The examples below are provided in both English and Chinese so agents can mirror the active note language while keeping a stable note shape.
Project Overview
English
# Project Overview
## What this project studies
- ...
## Why this problem is hard
- ...
## Current project positioning
- ...
## Most mature research direction so far
- ...中文
# 项目概览
## 这个项目研究什么
- ...
## 为什么这个问题难
- ...
## 当前项目定位
- ...
## 目前最成熟的研究分支
- ...Research Questions
English
# Research Questions
## Question 1
- ...
## Question 2
- ...中文
# 研究问题
## 问题 1
- ...
## 问题 2
- ...Experiment Note
English
# Experiment Name
## Goal
- ...
## Motivation from papers or prior results
- ...
## Setup
- ...
## Main steps
- ...
## Updates
- ...
## Findings
- ...
## Promotion criteria for Results
- ...
## Next steps
- ...中文
# 实验名称
## 目标
- ...
## 来自论文或已有结果的动机
- ...
## 设置
- ...
## 主要步骤
- ...
## 更新
- ...
## 发现
- ...
## 晋升到 Results 的条件
- ...
## 下一步
- ...Result Note
English
# Result Name
## Core conclusion
- ...
## Evidence
- ...
## Interpretation
- ...
## Reusable writing points
- ...
## Why it matters
- ...中文
# 结果名称
## 核心结论
- ...
## 证据
- ...
## 解读
- ...
## 可延续到写作中的内容
- ...
## 为什么重要
- ...Results Report Note
English
---
type: results-report
date: YYYY-MM-DD
experiment_line: example-line
round: 1
purpose: transfer-summary
status: active
source_artifacts:
- analysis-output/analysis-report.md
linked_experiments:
- Experiments/Example.md
linked_results:
- Results/Example-Result.md
---
# Example Experiment Line / Round 1 / transfer-summary / YYYY-MM-DD
## Executive summary
- ...
## Experiment identity and decision context
- ...
## Setup and evaluation protocol
- ...
## Main findings
- ...
## Statistical validation
- ...
## Figure-by-figure interpretation
- ...
## Failures / negative results / limitations
- ...
## Which evidence changed the decision
- ...
## Next actions
- ...
## Artifact and reproduction index
- ...中文
---
type: results-report
date: YYYY-MM-DD
experiment_line: example-line
round: 1
purpose: transfer-summary
status: active
source_artifacts:
- analysis-output/analysis-report.md
linked_experiments:
- Experiments/Example.md
linked_results:
- Results/Example-Result.md
---
# 示例实验线 / 第 1 轮 / transfer-summary / YYYY-MM-DD
## 执行摘要
- ...
## 实验身份与决策背景
- ...
## 设置与评测协议
- ...
## 主要发现
- ...
## 统计验证
- ...
## 图表逐项解读
- ...
## 失败案例 / 负结果 / 局限性
- ...
## 哪些证据改变了判断
- ...
## 下一步动作
- ...
## 产物与复现索引
- ...Paper Note
English
# Paper Title
## Citation
- ...
## Core claims
- ...
## Method
- ...
## Evidence
- ...
## Limitations
- ...
## Direct relevance to this repository
- ...
## Relation to other papers
- ...中文
# 论文标题
## 引文
- ...
## 核心主张
- ...
## 方法
- ...
## 证据
- ...
## 局限
- ...
## 与当前仓库的直接相关性
- ...
## 与其他论文的关系
- ...Daily Note
English
# Daily Note - YYYY-MM-DD
## Focus
- ...
## Progress
- ...
## Follow-up knowledge to promote
- ...
## Next steps
- ...中文
# 日志 - YYYY-MM-DD
## 关注重点
- ...
## 进展
- ...
## 后续可沉淀
- ...
## 下一步
- ...Writing Note
English
# Writing Item Name
## Purpose
- ...
## Supporting results
- ...
## Paper background or comparisons
- ...
## Draft argument
- ...
## What is still missing before publication use
- ...中文
# 写作对象名称
## 目的
- ...
## 有哪些结果支撑
- ...
## 论文背景或对比
- ...
## 草拟论点
- ...
## 距离可发表使用还差什么
- ...Papers -> Experiments -> Results -> Writing
Use this as the default durable research pipeline inside the project knowledge base.
Why this pipeline matters
The vault should not treat literature, experiments, results, and writing as isolated folders.
Default expectation: 1. Papers/ produces hypotheses, reusable methods, baselines, and evaluation criteria. 2. Experiments/ turns those into actionable test plans or updates an existing experiment line. 3. Results/ captures the durable findings that survive beyond one run or one day. 4. Writing/ turns those findings into external-facing synthesis: literature review, proposal text, draft claims, slides, rebuttal notes.
Daily/ is the staging area for temporary work and chronology, not the final destination for durable research objects.
Default handoff rules
Papers -> Experiments
Promote from Papers/ to Experiments/ when a paper note yields:
- a testable hypothesis,
- a method variation worth implementing,
- a baseline worth reproducing,
- an ablation worth adding,
- an evaluation protocol or metric worth adopting.
Default action:
- update the existing canonical experiment note if the idea belongs to an existing experiment line,
- otherwise create one new experiment note for the distinct experiment line,
- add a short back-link from the paper note to that experiment note.
Do not stop at “this paper is relevant”; push at least to “what should we test because of it?” when the turn supports that level of specificity.
Experiments -> Results
Promote from Experiments/ to Results/ when an experiment yields:
- a stable comparison,
- a repeatable failure pattern,
- a durable negative result,
- a mechanism insight,
- a decision-changing observation.
Default action:
- keep transient run noise in
Daily/or inside the experiment note, - create or update a result note only when the observation is stable enough to cite later,
- link the result note back to the experiment note and vice versa.
Do not create a result note for every run. Create one when the finding survives beyond raw logs.
Results -> Writing
Promote from Results/ to Writing/ when a result yields:
- a claim that belongs in a paper, report, slide, or proposal,
- a useful comparison matrix,
- a project narrative update,
- a conclusion that should appear in a literature review or discussion section.
Default action:
- update an existing writing note when the output object already exists,
- otherwise create one writing note per external object (review, proposal, draft section, slide outline, rebuttal block),
- keep links back to the result notes and key paper notes that support the claim.
Do not let writing drift away from evidence. Every durable writing claim should link back to supporting results, and when useful, to the motivating papers.
Folder-by-folder default questions
For a paper note
Ask:
- What is the main reusable idea?
- Does it change what we should test?
- Which existing experiment line should absorb it?
- Does it belong in the active writing narrative yet?
For an experiment note
Ask:
- Which paper or prior result motivated this experiment?
- What decision would this experiment change?
- What evidence would justify promotion into
Results/? - What writing object would benefit if this experiment succeeds or fails?
For a result note
Ask:
- What is the durable claim?
- What evidence supports it?
- Which experiments and papers does it connect?
- Which writing artifact should absorb this claim next?
For a writing note
Ask:
- Which result notes support this text?
- Which paper notes provide context or comparison?
- Is this writing object current, or should it be updated from newer results?
Main anti-patterns
Avoid these weak workflows:
- paper notes that never produce experiment decisions,
- experiment notes that never clarify what finding would count as durable,
- result notes that never feed any writing object,
- writing notes that drift away from linked evidence,
- keeping durable insights in
Daily/instead of promoting them.
Default promotion heuristic
When unsure, use this order: 1. update the existing paper note, 2. if it changes what should be tested, update or create the experiment note, 3. if it changes what is now believed, update or create the result note, 4. if it changes what should be said externally, update the writing note.
This is the default durable research path unless the user clearly wants a narrower operation.
Obsidian Project Knowledge Base Schema
Repository-local memory files
.claude/project-memory/registry.yaml— registry keyed byproject_id.claude/project-memory/<project_id>.md— compact project memory snapshot used on project turns
Note: registry.yaml is currently JSON-formatted on disk for historical compatibility.
Optional per-project registry fields:
note_language— note language for generated/synced notes. Supported values:en,zh-CN.
Language resolution priority: 1. project config in .claude/project-memory/registry.yaml 2. environment variable OBSIDIAN_NOTE_LANGUAGE 3. default en
Vault layout
Research/{project-slug}/
00-Hub.md
01-Plan.md
Knowledge/
Papers/
Experiments/
Results/
Reports/
Writing/
Daily/
Archive/Role of each top-level location
00-Hub.md— project homepage, current state, must-remember numbers, key links01-Plan.md— active goals, tasks, open questions, next actionsKnowledge/— stable project understanding such as background, research questions, method survey, data protocol, source inventoryPapers/— paper notes, literature summaries, related-work assetsExperiments/— experiment designs, runbooks, ablations, mechanism studiesResults/— canonical durable findings, diagnostics, figure/table indexes, cross-experiment conclusionsResults/Reports/— internal experiment round reports and batch retrospectives with stable namingWriting/— paper drafting, slides, proposal text, rebuttal materialDaily/— daily logs, lightweight sync queue, scratch notes, meeting fragmentsArchive/— inactive or historical material that should not stay in the main working surface
Minimum note types
projectdailypaperexperimentresultresults-reportsynthesismetawritingtask
Main design rule
This schema is intentionally small. Prefer a few durable notes over many placeholder notes.
Script vs Agent Boundary
Use this guide to decide whether a task belongs in project_kb.py or must remain agent-driven.
Good fit for the script
These tasks are low-freedom, deterministic, and should behave the same every time:
- detect whether a repo is bound to a project vault
- bootstrap the standard vault structure
- sync repo-driven state into daily, hub, plan, memory, and auto-sync notes
- list or suggest the canonical notes to read for a question shape
- archive, purge, or rename a single note with direct-link repair in explicit index notes
- maintain source inventory and codebase overview
Current script-facing commands:
detectbootstrapsynclifecyclequery-contextfind-canonical-notenote-lifecycle
Must stay with the agent
These tasks require semantic judgment and should not be hard-coded into the script:
- deciding whether a new Markdown file is durable knowledge or raw material
- deciding whether to promote, merge, or stage a new Markdown file
- deciding which existing note is the canonical note when multiple semantic candidates exist
- synthesizing background from many project documents
- interpreting experimental meaning or result significance
- deciding whether a note should be split or merged based on conceptual overlap
- deciding whether a result is stable enough for
Results/
Practical rule
If the task can be framed as:
- “find”, “move”, “rename”, “archive”, “sync”, or “suggest reads”
it is probably script-suitable.
If the task can be framed as:
- “understand”, “interpret”, “decide meaning”, “summarize”, “merge concepts”, or “promote to durable knowledge”
it should remain agent-driven.
Workflow
1. Detect
Run:
python3 scripts/project_kb.py detect --cwd "$PWD"Use this to decide whether the repo:
- is already bound,
- should be bootstrapped,
- or should be left alone.
2. Bootstrap
Bootstrap only when the repository is a strong research-project candidate and no binding exists yet.
python3 scripts/project_kb.py bootstrap --cwd "$PWD" --vault-path "$OBSIDIAN_VAULT_PATH"Bootstrap should create only the compact schema from SCHEMA.md, including Results/Reports/ for internal experiment reports.
To bootstrap Chinese notes explicitly:
python3 scripts/project_kb.py bootstrap --cwd "$PWD" --vault-path "$OBSIDIAN_VAULT_PATH" --note-language zh-CNLanguage priority for generated/synced notes: 1. per-project note_language in .claude/project-memory/registry.yaml 2. environment variable OBSIDIAN_NOTE_LANGUAGE 3. default en
Section updates remain compatible with both English and Chinese headings so older notes can still sync safely after switching the configured language.
3. Daily or repo-driven sync
Use:
python3 scripts/project_kb.py sync --cwd "$PWD" --scope autoUse sync for deterministic state maintenance only:
- refresh
00-Hub.md - refresh
01-Plan.md - refresh project memory
- write daily sync information
- keep source inventory and codebase overview fresh
Do not rely on sync to derive project meaning from raw files.
For read-side assistance or single-note lifecycle operations, use:
python3 scripts/project_kb.py query-context --cwd "$PWD" --kind broad
python3 scripts/project_kb.py query-context --cwd "$PWD" --kind result --query "syllable-channel"
python3 scripts/project_kb.py find-canonical-note --cwd "$PWD" --kind experiment --query "freezing S7 speaking"
python3 scripts/project_kb.py note-lifecycle --cwd "$PWD" --mode archive --note "Results/Old-Result.md"4. Agent-first import or synthesis
When the vault lacks background or context, do not extend the script first.
Instead: 1. ask an agent to read the most informative project sources, 2. synthesize project-level knowledge, 3. write durable notes back into Knowledge/, Experiments/, Results/, Results/Reports/, or Papers/.
5. Advance along the main research path
For substantive research turns, prefer advancing knowledge along this path:
Papers -> Experiments -> Results -> WritingTypical progression:
- new paper understanding -> update
Papers/and decide whether an experiment note should absorb a new hypothesis, baseline, or evaluation rule - experiment planning or execution -> update
Experiments/and decide what evidence would justify a result note - stable finding -> update
Results/and decide whether a round or batch retrospective should be written underResults/Reports/ - draft or review work -> update
Writing/and keep links back to supporting results and papers
Do not treat these folders as isolated silos. The default durable workflow is to move knowledge forward across them when the turn supports it.
6. Incremental update rule
For most turns, write the minimum durable delta only.
Examples:
- small engineering change ->
Daily/plus project memory - new experiment design ->
Experiments/ - new result interpretation ->
Results/ - new internal experiment retrospective ->
Results/Reports/ - new project framing ->
Knowledge/ - new paper note ->
Papers/
7. Ingest a new Markdown file
When a new .md file appears, do not route it by path alone.
Use this sequence: 1. classify it as knowledge, paper, experiment, result, writing, or daily, 2. decide whether it is a durable note or raw material, 3. choose one of:
- promote into the matching top-level folder,
- merge into an existing canonical note,
- stage to Daily when it is still unstable.
Examples:
- new
plan/new_idea.md-> usually summarize first, then update01-Plan.mdorKnowledge/Research-Questions.md - a complete experiment summary -> usually promote to
Results/Reports/, and updateResults/if a stable conclusion is now supported - a scratch meeting memo -> usually stage in
Daily/
project_kb.py may manage state around this process, but it does not decide promote vs merge.
8. Update / archive / purge durable notes
For durable notes:
- update the canonical note when the object already exists,
- create a new note only when the object is genuinely distinct,
- archive by default when the user wants to remove something,
- purge only on explicit permanent-delete intent.
When archiving or purging, repair direct links in 00-Hub.md, 01-Plan.md, and explicit index notes.
9. Lifecycle actions
Default removal behavior is archive:
python3 scripts/project_kb.py lifecycle --cwd "$PWD" --mode archiveOnly purge when the user explicitly asks for permanent deletion.
#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
if str(SCRIPT_DIR) not in sys.path:
sys.path.insert(0, str(SCRIPT_DIR))
import project_kb # type: ignore
NOTE_WIDTH = 320
NOTE_HEIGHT = 220
def write_if_changed(path: Path, content: str) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
if path.exists() and path.read_text(encoding='utf-8') == content:
return
path.write_text(content, encoding='utf-8')
def file_node(node_id: str, rel_path: str, x: int, y: int) -> dict:
return {
'id': node_id,
'type': 'file',
'file': rel_path,
'x': x,
'y': y,
'width': NOTE_WIDTH,
'height': NOTE_HEIGHT,
}
def text_node(node_id: str, text: str, x: int, y: int, width: int = 280, height: int = 120) -> dict:
return {
'id': node_id,
'type': 'text',
'text': text,
'x': x,
'y': y,
'width': width,
'height': height,
}
def edge(edge_id: str, from_node: str, to_node: str, label: str = '') -> dict:
payload = {
'id': edge_id,
'fromNode': from_node,
'toNode': to_node,
'fromSide': 'right',
'toSide': 'left',
}
if label:
payload['label'] = label
return payload
def build_base_content(folder: str, title: str, order: list[str], extra_filters: list[str] | None = None) -> str:
filter_expr = [f'file.inFolder("{folder}")']
if extra_filters:
filter_expr.extend(extra_filters)
if len(filter_expr) == 1:
filters_block = f"filters: '{filter_expr[0]}'"
else:
inner = '\n'.join(f" - '{expr}'" for expr in filter_expr)
filters_block = f"filters:\n and:\n{inner}"
order_block = '\n'.join(f' - {item}' for item in order)
return f'''# Generated by Claude Scholar project_views.py
{filters_block}
properties:
title:
displayName: "Title"
status:
displayName: "Status"
updated:
displayName: "Updated"
year:
displayName: "Year"
venue:
displayName: "Venue"
zotero_key:
displayName: "Zotero Key"
linked_experiment:
displayName: "Experiment"
decision:
displayName: "Decision"
views:
- type: table
name: "{title}"
order:
{order_block}
'''
def generate_bases(project_root: Path) -> list[str]:
views_root = project_root / 'Views'
files = {
'papers.base': build_base_content(
'Papers', 'Papers',
['file.name', 'title', 'year', 'venue', 'status', 'updated', 'zotero_key']
),
'experiments.base': build_base_content(
'Experiments', 'Experiments',
['file.name', 'title', 'status', 'updated']
),
'results.base': build_base_content(
'Results', 'Results',
['file.name', 'title', 'linked_experiment', 'decision', 'updated']
),
'tasks.base': build_base_content(
'Daily', 'Tasks',
['file.name', 'title', 'status', 'updated'],
extra_filters=['file.ext == "md"']
),
}
written = []
for name, content in files.items():
path = views_root / name
write_if_changed(path, content)
written.append(str(path))
return written
def existing_rel(project_root: Path, rel: str) -> str | None:
path = project_root / rel
if path.exists():
return rel
return None
def generate_project_canvas(project_root: Path) -> str:
maps_root = project_root / 'Maps'
nodes = []
edges = []
center = text_node('n0', 'Project map\nMain canonical notes', 40, 220)
nodes.append(center)
candidate_notes = [
'00-Hub.md',
'01-Plan.md',
'Knowledge/Project-Overview.md',
'Knowledge/Research-Questions.md',
'Knowledge/Literature-Overview.md',
'Writing/literature-review.md',
]
x = 420
y = 40
idx = 1
for rel in candidate_notes:
if existing_rel(project_root, rel):
node_id = f'n{idx}'
nodes.append(file_node(node_id, rel, x, y))
edges.append(edge(f'e{idx}', 'n0', node_id))
y += 260
idx += 1
content = json.dumps({'nodes': nodes, 'edges': edges}, ensure_ascii=False, indent=2) + '\n'
path = maps_root / 'project.canvas'
write_if_changed(path, content)
return str(path)
def note_title(path: Path) -> str:
return path.stem
def result_links_experiment(result_path: Path, experiment_path: Path) -> bool:
text = result_path.read_text(encoding='utf-8', errors='ignore')
stem = experiment_path.stem
return stem in text or f'[[Experiments/{stem}' in text
def generate_experiments_canvas(project_root: Path) -> str:
maps_root = project_root / 'Maps'
exp_paths = sorted((project_root / 'Experiments').glob('*.md')) if (project_root / 'Experiments').exists() else []
res_paths = sorted((project_root / 'Results').glob('*.md')) if (project_root / 'Results').exists() else []
nodes = [text_node('n0', 'Experiments → Results', 40, 220)]
edges = []
node_counter = 1
exp_ids: dict[Path, str] = {}
res_ids: dict[Path, str] = {}
for i, exp_path in enumerate(exp_paths):
node_id = f'n{node_counter}'
node_counter += 1
exp_ids[exp_path] = node_id
rel = str(exp_path.relative_to(project_root)).replace('\\', '/')
nodes.append(file_node(node_id, rel, 420, 40 + i * 260))
edges.append(edge(f'e{len(edges)+1}', 'n0', node_id, 'tests'))
for i, res_path in enumerate(res_paths):
node_id = f'n{node_counter}'
node_counter += 1
res_ids[res_path] = node_id
rel = str(res_path.relative_to(project_root)).replace('\\', '/')
nodes.append(file_node(node_id, rel, 860, 40 + i * 260))
for exp_path, exp_id in exp_ids.items():
linked = False
for res_path, res_id in res_ids.items():
if result_links_experiment(res_path, exp_path):
edges.append(edge(f'e{len(edges)+1}', exp_id, res_id, 'evidence'))
linked = True
if not linked:
# keep minimal visibility even if explicit links are absent
pass
content = json.dumps({'nodes': nodes, 'edges': edges}, ensure_ascii=False, indent=2) + '\n'
path = maps_root / 'experiments.canvas'
write_if_changed(path, content)
return str(path)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description='Generate optional Obsidian Bases and canvas helpers for a bound project.')
parser.add_argument('--cwd', default='.')
parser.add_argument('--include-canvases', action='store_true', help='Also generate Maps/project.canvas and Maps/experiments.canvas')
parser.add_argument('--project-id', default='')
return parser.parse_args()
def main() -> None:
args = parse_args()
repo_root = project_kb.find_repo_root(Path(args.cwd).resolve())
binding = project_kb.resolve_binding(repo_root, args.project_id or None)
outputs = {'views': generate_bases(binding.project_root), 'canvases': []}
if args.include_canvases:
outputs['canvases'] = [
generate_project_canvas(binding.project_root),
generate_experiments_canvas(binding.project_root),
]
print(json.dumps(outputs, ensure_ascii=False, indent=2))
if __name__ == '__main__':
main()
Related skills
FAQ
Does obsidian-project-memory require MCP?
No, it does not require MCP, API keys, REST plugins, or .base artifacts.
How does it split work between scripts and agents?
Scripts handle project state management; agents handle project understanding and synthesis.