AgenticSecond Brain

Second
Brain

An Obsidian vault that Claude can read, query, and write to. 360+ atomic notes, one idea each.

Drag to turn. Point at a note to see its links; click to pin it.

type: decisionproject: [second-brain-bridge]Tool Schema Design
type: decisionproject: [hipm]n8n over Make

Colour shows the folder a note sits in. Position, links and dot size are drawn for this page; the cards are sample notes.

notes
0+
note types
0
MCP tools
0

Plain Markdown files, one idea each. Claude reads and writes them through nine MCP tools.

ObsidianMCP SDKTypeScriptMarkdownFrontmatterYAML

Anatomy of a note

Frontmatter on top, the idea below. Point at a part on either side.

01-projects/luccafaust-dev/decisions/portfolio-bilingual-toggle.md

Source

---type: decisionproject: [luccafaust-dev]tags: [i18n, next-intl, toggle]date: 2026-04-20---
# Portfolio bilingual — EN + DE with toggle
Portfolio ships bilingual (EN + DE), switchable via a top-nav toggle. The i18n pass happens once content is solid, not in parallel, so the two languages don't drift.**Why:** … **How to apply:** …

Reading view

Portfolio bilingual — EN + DE with toggle

type
decision
project
luccafaust-dev
tags
i18nnext-intltoggle
date
2026-04-20

Portfolio ships bilingual (EN + DE), switchable via a top-nav toggle. The i18n pass happens once content is solid, not in parallel, so the two languages don't drift.

Why: … How to apply: …

Linked by topic

Every line is a wiki-link. Point at a note to light its links.

Graph view8 sample notes · 12 links

Folders that mirror the work

Inbox, projects, knowledge, daily, research, templates. Open a note to see its frontmatter.

~/Documents/second-brainsample notes

01-projects/second-brain-bridge/

Zod Validation

type
learning
project
second-brain-bridge
tags
mcpvalidationzod
date
2026-03-15

Runtime validation with Zod schemas guarantees tool inputs and outputs are type-safe.

Nine tools, three jobs

Three tools find notes, three read, three write. Pick one to see a sample call.

.mcp-server/src/index.ts9 tools
Claudeasks through MCP

Findby meaning or by frontmattervault → Claude

Readnotes, project context, skillsvault → Claude

Writecreate, update, linkClaude → vault

Vault360+ Markdown notes

vault_recall

Hybrid recall — semantic + keyword + project filter (default)

takestaskprojectlimit

Sample call

{
  "task": "decisions about automation",
  "limit": 2
}

Sample result

{
  "notes": [
    { "path": "01-projects/hipm/decisions/n8n-statt-make.md",
      "title": "n8n over Make", "score": 0.94,
      "type": "decision", "project": ["hipm"],
      "excerpt": "n8n replaces Make.com as the central..." },
    { "path": "02-knowledge/skills/webhook-patterns.md",
      "title": "Webhook Patterns", "score": 0.61,
      "type": "skill", "project": [],
      "excerpt": "Webhook-based integrations follow..." }
  ],
  "recall_summary": "2 relevante Notes: 1 decision, 1 skill"
}

How the search works

Every note becomes a vector

Ollama runs nomic-embed-text on localhost and turns each note into a vector. Long notes are cut at a paragraph break where possible. Each cached vector keeps the name of its model.

src/embeddings/ollama-client.tslines 17–37
  prepareText(text: string): string {    if (text.length <= this.maxChars) return text;    // Truncate at paragraph boundary if possible to preserve semantic coherence    const truncated = text.slice(0, this.maxChars);    const lastPara = truncated.lastIndexOf('\n\n');    return lastPara > this.maxChars * 0.7 ? truncated.slice(0, lastPara) : truncated;  }   async embed(text: string): Promise<Float32Array> {    const prepared = this.prepareText(text);    const res = await fetch(`${this.host}/api/embeddings`, {      method: 'POST',      headers: { 'Content-Type': 'application/json' },      body: JSON.stringify({ model: this.model, prompt: prepared }),    });    if (!res.ok) {      throw new Error(`Ollama embedding failed: ${res.status} ${res.statusText}`);    }    const data = await res.json() as { embedding: number[] };    return new Float32Array(data.embedding);  }

The question takes the same path

The same model embeds the question. Cosine similarity compares it with every cached note vector; the closest notes come back first, ten by default, optionally filtered by project or type.

questionn8n over Make0.94Webhook Patterns0.87Another topic0.31
The score is the cosine of the angle between two vectors; length does not count. Drawn flat with sample scores; nomic-embed-text vectors have 768 dimensions.
src/embeddings/similarity.tslines 3–12
export function cosineSimilarity(a: Float32Array, b: Float32Array): number {  let dot = 0, normA = 0, normB = 0;  for (let i = 0; i < a.length; i++) {    dot += a[i] * b[i];    normA += a[i] * a[i];    normB += b[i] * b[i];  }  const denom = Math.sqrt(normA) * Math.sqrt(normB);  return denom === 0 ? 0 : dot / denom;}

When Ollama is not there

If Ollama is unreachable when the server starts, vault_search scores words instead: title hits count three times, tags twice, text once. Coarser ranking, but search keeps answering.

src/index.tslines 72–84
    const limit = rawLimit ?? 10;    let results;    if (ollamaAvailable) {      const queryEmbedding = await ollama.embed(query);      results = findTopK(queryEmbedding, embeddingsCache, limit, { project, type });    } else {      // Keyword fallback      const notes = listNotes(VAULT_PATH).map(p => {        const n = readNote(VAULT_PATH, p);        return { path: p, title: n.title, tags: n.frontmatter.tags ?? [], content: n.content };      });      results = keywordSearch(query, notes).slice(0, limit);    }

Why it runs on this machine

No note is sent anywhere to be embedded, no query costs money, and search works offline. A new embedding model re-embeds only the stale vectors, on the next start.

This machine

  1. Markdown filesthe vault folder
  2. Ollamanomic-embed-text on localhost
  3. Vector cacheeach vector with its model
  4. MCP serverranks, filters, reads
Claudeasks through MCP
Embedding and ranking happen inside the dashed line. Claude reaches the vault only through the server.

How notes get written

Claude writes them itself

Standing instructions give each note type a trigger. When one fires, Claude writes the note unprompted, into the folder of its type.

  • decisionA choice with effects for six months or more01-projects/‹project›/decisions/
  • learningUnexpected behaviour, a workaround, an insight worth reusing01-projects/‹project›/learnings/
  • skillA process used three times or more, or written down as steps02-knowledge/skills/
  • referenceA tool, source or system useful in more than one context01-projects/‹project›/references/
Skipped on purpose: fixes without a new insight, renames, raw research output.

Through the server, with a schema

vault_write refuses a note without a type and embeds it right away. vault_update merges frontmatter and re-embeds. vault_link adds a wiki-link under a chosen heading and skips one that already exists.

  1. 1vault_writecreates the file

    learnings/error-boundaries.md

    ---type: learningtags: [mcp, errors]---MCP tools should catch and wrap…

    returns "embedded": true

  2. 2vault_updatemerges frontmatter

    learnings/error-boundaries.md

    ---type: learningtags: [mcp, errors]status: active---MCP tools should catch and wrap…

    returns "re_embedded": true

  3. 3vault_linkadds a link under a heading

    learnings/error-boundaries.md

    ---type: learning…---MCP tools should catch and wrap…## Related[[mcp-server-design]]

    returns "linked": true

A sample note. Marked lines are what each call adds.

The vault in daily use

Part of every session

A hook loads vault context with every prompt; another asks at the end of a turn whether a decision is worth a note. Before planning, Claude checks the project's earlier decisions so a new plan does not contradict them.

  1. Every prompthookloads vault context
  2. Morning/daily-briefthe day's briefing
  3. Starting on a project/brain-contextloads the project's context
  4. Capturing/braindump/url-dump/auto-researchthoughts, links and research become notes
  5. End of a turnhookis a decision worth a note?
  6. Review/weekly-checkin/knowledge-consolidationthe weekly check-in, consolidating what is known
Hooks run by themselves; the seven slash commands are typed when needed.

Six decisions behind it

  • Plain Markdown files

    Readable, git-trackable, editable without the server. The vault stays portable.

  • One idea per note

    No long documents. Each note can be found and linked on its own.

  • Frontmatter as schema

    Filter by type, project, status or date, not by full text.

  • Embeddings stay local

    Ollama on localhost: no note leaves the machine to be embedded.

  • Vectors know their model

    Each vector records its model; a model swap re-embeds only stale ones.

  • Keyword fallback

    No Ollama at start? Search answers by keywords. Ranking suffers, the vault keeps working.