Claude Code x Obsidian: estrutura do Vault, permissions, templates e auditoria de links
Workflow prático para Claude Code e Obsidian: daily logs, handoff, snippets, content ops e auditoria de links.
Um Vault do Obsidian fica mais valioso com o tempo, mas também exige mais manutenção. Daily notes se acumulam, notas de projeto ficam desatualizadas, snippets de código perdem contexto de versão e ideias de conteúdo param de apontar para os links internos ou CTAs corretos. Claude Code pode ajudar porque, no fundo, um Vault é uma pasta com arquivos Markdown.
O caminho seguro não é pedir para a IA reorganizar tudo. O workflow útil é limitado: estrutura pequena, permissions estreitas, templates reutilizáveis e uma auditoria de links depois das alterações. Para iniciantes, o Vault é a pasta de notas; o harness é a base de trabalho que diz ao agente onde ele pode ler, escrever e verificar.
Este guia cobre quatro use case: daily logs, project handoff, code snippets e content operations. Também mostra cada pitfall e risk importante, porque o maior problema costuma ser um link quebrado, uma Property YAML inválida ou uma nota privada lida sem necessidade.
Modelo de integração
A ajuda oficial do Obsidian explica que internal links podem usar Wikilinks como [[Nome da nota]] ou links Markdown. Daily notes é um core plugin para notas por data. Templates pode inserir valores como {{date}}, e Properties usa YAML no topo da nota. Veja as páginas oficiais de internal links, Daily notes, Templates, Properties e Web Clipper templates.
No Claude Code, a fronteira de segurança vem de settings e permissions. CLAUDE.md ensina as regras do Vault. .claude/settings.json limita leitura, escrita e comandos.
flowchart LR
A["Inbox"] --> B["Claude Code review"]
B --> C["Daily logs"]
B --> D["Projects"]
B --> E["Content ops"]
C --> F["Obsidian links"]
D --> F
E --> F
F --> G["Link audit"]
Markdown no Obsidian continua sendo a fonte da verdade. Claude Code ajuda a organizar, resumir, preparar rascunhos e verificar links.
Comece com uma estrutura pequena
Use pastas que correspondam a trabalho real.
mkdir -p inbox daily projects content-ops snippets templates scripts archive private
| Pasta | Uso | Trabalho seguro para Claude Code |
|---|---|---|
inbox/ | capturas brutas e Web Clipper | criar e classificar |
daily/ | daily logs e memória de trabalho | criar, acrescentar, resumir ontem |
projects/ | project handoff e decisões | atualizar handoff |
content-ops/ | ideias de artigos, CTA, publicação | organizar drafts e links |
snippets/ | comandos e exemplos de código | adicionar contexto e tags |
templates/ | templates do Obsidian | ler; editar só com aprovação |
archive/ | notas encerradas | não editar |
private/ | dados pessoais ou secretos | não ler |
Essa estrutura cobre casos concretos. Daily logs carregam tarefas não concluídas. Project handoff explica objetivo, estado, próxima ação e risk. Snippets guardam comando executável, versão e failure case. Content operations verifica links oficiais, links internos, /products/ e /training/.
Adicione CLAUDE.md
Coloque este arquivo na raiz do Vault.
# Obsidian Vault Rules
## Purpose
- This vault stores daily logs, project handoffs, code snippets, and content operations notes.
- Keep notes useful in Obsidian without requiring Claude Code to read private files.
## Directory policy
- `daily/`: create or update daily notes in `YYYY-MM-DD.md`.
- `projects/`: maintain one handoff note per active project.
- `content-ops/`: maintain article plans, CTA checks, and publishing notes.
- `snippets/`: store runnable commands and code examples with context.
- `templates/`: read freely, but ask before editing.
- `archive/` and `private/`: do not edit. Do not summarize private files.
## Note rules
- Use Wikilinks like `[[Project name]]` for internal links.
- Use YAML properties at the top of notes.
- Keep one paragraph under five lines.
- Add a `source:` property when a note comes from a URL.
- Add `status: draft`, `status: active`, or `status: done`.
## Safety rules
- Never rename existing notes without asking first.
- Never rewrite `.obsidian/` settings.
- Before bulk edits, list the target files and wait for approval.
- After changes, run `node scripts/audit-wikilinks.cjs .`.
O pitfall comum é pedir “organize meu Vault”. Claude Code passa a adivinhar pastas, títulos e tags. A saída pode parecer limpa, mas quebrar pesquisa, Graph view e backlinks.
Configure permissions estreitas
Crie .claude/settings.json.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Read(./CLAUDE.md)",
"Read(./daily/**)",
"Read(./projects/**)",
"Read(./content-ops/**)",
"Read(./snippets/**)",
"Read(./templates/**)",
"Read(./scripts/**)",
"Edit(./daily/**)",
"Edit(./projects/**)",
"Edit(./content-ops/**)",
"Edit(./snippets/**)",
"Write(./inbox/**)",
"Write(./daily/**)",
"Write(./projects/**)",
"Write(./content-ops/**)",
"Write(./snippets/**)",
"Bash(node scripts/audit-wikilinks.cjs .)"
],
"ask": [
"Edit(./templates/**)",
"Bash(git *)",
"WebFetch"
],
"deny": [
"Read(./private/**)",
"Read(./**/.env)",
"Read(./**/.env.*)",
"Edit(./.obsidian/**)",
"Edit(./archive/**)",
"Write(./archive/**)",
"Bash(rm *)",
"Bash(del *)"
]
}
}
Essa configuração permite o trabalho diário, mas pede confirmação para templates, Git e WebFetch. Evite bypass amplo em Vaults reais.
Três templates do Obsidian
O daily template deve ser leve.
---
date: "{{date:YYYY-MM-DD}}"
status: active
tags:
- daily
---
# {{date:YYYY-MM-DD}}
## Today
- [ ]
## Learned
-
## Questions
-
## Links
- [[Weekly review]]
O project handoff deixa a próxima ação visível.
---
status: active
owner: Masa
tags:
- project
- handoff
updated: "{{date:YYYY-MM-DD}}"
---
# Project handoff: {{title}}
## Goal
## Current state
## Next action
- [ ]
## Decisions
-
## Risks and pitfall
-
## Links
- [[Daily note]]
- [[Related snippet]]
O template de content operations inclui monetização desde o planejamento.
---
status: draft
channel: blog
source:
target_cta:
- /products/
- /training/
tags:
- content-ops
---
# Content ops note: {{title}}
## Search intent
## Reader problem
## Outline
## Internal links
- [[Claude Code approval sandbox guide]]
- [[Claude Code documentation generation]]
## Monetization CTA
- Product CTA:
- Training CTA:
## Publish checklist
- [ ] Official links checked
- [ ] Code examples tested
- [ ] Broken internal links audited
Leia também approval e sandbox, documentation generation e content funnel audit. Materiais reutilizáveis vão para products e adoção em equipe para training.
Audite links internos com Node
Salve como scripts/audit-wikilinks.cjs.
#!/usr/bin/env node
const fs = require("node:fs");
const path = require("node:path");
const vaultRoot = path.resolve(process.argv[2] || ".");
const ignoredDirs = new Set([".git", ".obsidian", ".trash", "node_modules"]);
const allFiles = [];
const markdownFiles = [];
function walk(dir) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
if (ignoredDirs.has(entry.name)) continue;
const full = path.join(dir, entry.name);
if (entry.isDirectory()) {
walk(full);
} else if (entry.isFile()) {
allFiles.push(full);
if (entry.name.toLowerCase().endsWith(".md")) markdownFiles.push(full);
}
}
}
function toPosix(filePath) {
return filePath.split(path.sep).join("/");
}
function withoutMd(value) {
return value.replace(/\.md$/i, "");
}
function stripTarget(raw) {
return raw.split("|")[0].split("#")[0].split("^")[0].trim();
}
function safeDecode(value) {
try {
return decodeURIComponent(value);
} catch {
return value;
}
}
function isExternal(target) {
return /^(https?:|mailto:|obsidian:|#|\/)/i.test(target);
}
function candidateKeys(target, fromFile) {
const clean = safeDecode(stripTarget(target));
if (!clean) return [];
const keys = new Set();
const normalized = toPosix(path.normalize(clean));
keys.add(normalized);
keys.add(withoutMd(normalized));
if (clean.includes("/") || clean.includes("\\")) {
const fromDir = path.dirname(toPosix(path.relative(vaultRoot, fromFile)));
const relative = toPosix(path.normalize(path.join(fromDir, clean)));
keys.add(relative);
keys.add(withoutMd(relative));
} else {
keys.add(withoutMd(path.posix.basename(normalized)));
keys.add(path.posix.basename(normalized));
}
return [...keys].filter(Boolean);
}
walk(vaultRoot);
const byPath = new Map();
const byBase = new Map();
for (const file of allFiles) {
const rel = toPosix(path.relative(vaultRoot, file));
const lowerRel = rel.toLowerCase();
byPath.set(lowerRel, file);
if (rel.toLowerCase().endsWith(".md")) byPath.set(withoutMd(lowerRel), file);
const base = rel.toLowerCase().endsWith(".md")
? withoutMd(path.posix.basename(rel)).toLowerCase()
: path.posix.basename(rel).toLowerCase();
const list = byBase.get(base) || [];
list.push(file);
byBase.set(base, list);
}
const problems = [];
const wikilink = /!?\[\[([^\]]+)\]\]/g;
const markdownLink = /!?\[[^\]]*\]\(([^)]+)\)/g;
for (const file of markdownFiles) {
const text = fs.readFileSync(file, "utf8");
const rel = toPosix(path.relative(vaultRoot, file));
const targets = [];
let match;
while ((match = wikilink.exec(text))) targets.push(match[1]);
while ((match = markdownLink.exec(text))) {
const target = match[1].replace(/^<|>$/g, "").trim();
if (!isExternal(target)) targets.push(target);
}
for (const target of targets) {
const clean = stripTarget(target);
if (!clean || isExternal(clean)) continue;
const keys = candidateKeys(clean, file);
const pathHit = keys.some((key) => byPath.has(key.toLowerCase()));
const baseHits = keys.flatMap((key) => byBase.get(path.posix.basename(key).toLowerCase()) || []);
if (!pathHit && baseHits.length === 0) {
problems.push(`${rel} -> missing [[${clean}]]`);
} else if (!pathHit && baseHits.length > 1) {
problems.push(`${rel} -> ambiguous [[${clean}]] (${baseHits.length} matches)`);
}
}
}
if (problems.length) {
console.error("Broken or ambiguous internal links:");
for (const problem of problems) console.error(`- ${problem}`);
process.exit(1);
}
console.log(`OK: checked ${markdownFiles.length} Markdown files in ${vaultRoot}`);
Execute:
node scripts/audit-wikilinks.cjs .
Prompt delimitado:
Read `daily/2026-06-02.md` and `projects/site-refresh.md`.
Create `daily/2026-06-03.md` from `templates/daily.md`.
Carry over unfinished tasks only when they still have an owner.
Do not edit `.obsidian/`, `archive/`, or `private/`.
After editing, run `node scripts/audit-wikilinks.cjs .` and report the result.
Pitfalls comuns
Primeiro: permitir edição de .obsidian/. Plugins, temas e atalhos não são notas comuns.
Segundo: renomear notas fora do Obsidian. Bulk rename pode quebrar backlinks.
Terceiro: YAML Properties sem aspas. Use related: "[[Project name]]".
Quarto: daily notes pesadas demais. Template que ninguém preenche vira ruído.
Quinto: content operations não é só escrita. Um artigo público precisa de links oficiais, links internos, CTA e verificação.
O que Masa testou
No Vault de teste de Masa, os melhores resultados vieram de dois workflows: levar tarefas inacabadas para a próxima daily note e auditar links antes de publicar notas de conteúdo. A pior experiência foi pedir “limpe todo o Vault”; Claude Code criou tags e headings demais. Permissions estreitas, templates leves e auditoria Node deram um processo mais estável.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.
Artigos relacionados
Escada de segurança de permissões no Claude Code
Amplie de read-only para edições limitadas, comandos de prova e deploy checks sem perder controle.
Claude Code Small PR Proof Pack: pequenas mudanças fáceis de revisar
Um pacote de prova para PRs do Claude Code: diff, checks, URL pública, CTA e rollback.
Gate de revisão antes do commit com Claude Code
Revisão antes do commit com Claude Code: diff, build, URL pública, Gumroad, consultoria, testes e arquivos fora do escopo.