Tips & Tricks (Diperbarui: 3/6/2026)

Claude Code x Obsidian: struktur Vault, permissions, template, dan audit link

Workflow aman Claude Code dan Obsidian untuk daily logs, handoff, snippets, content ops, dan audit internal link.

Claude Code x Obsidian: struktur Vault, permissions, template, dan audit link

Vault Obsidian makin bernilai ketika dipakai lama, tetapi perawatannya juga makin berat. Daily notes menumpuk, catatan proyek tertinggal dari kondisi terbaru, snippets kode kehilangan konteks versi, dan ide artikel tidak lagi tersambung ke internal link atau CTA yang tepat. Claude Code bisa membantu karena Vault pada dasarnya adalah folder berisi file Markdown.

Pola yang aman bukan meminta AI merapikan semuanya. Workflow yang lebih stabil adalah memberi batas: struktur folder kecil, permissions ketat, template yang bisa dipakai ulang, dan audit link setelah perubahan. Untuk pemula, Vault adalah folder catatan; harness adalah kerangka kerja yang memberi tahu agen area mana yang boleh dibaca, ditulis, dan diverifikasi.

Panduan ini membahas empat use case: daily logs, project handoff, code snippets, dan content operations. Setiap pitfall dan risk utama juga dibahas, karena masalah terbesar biasanya bukan kalimat yang kurang halus, melainkan link rusak, YAML Properties keliru, atau catatan private terbaca.

Model integrasi

Dokumentasi resmi Obsidian menjelaskan internal link dengan Wikilink seperti [[Nama note]] atau format Markdown. Daily notes adalah core plugin untuk catatan berbasis tanggal. Templates dapat memasukkan nilai seperti {{date}}, dan Properties menyimpan metadata YAML di bagian atas note. Rujukan resmi: internal links, Daily notes, Templates, Properties, dan Web Clipper templates.

Di sisi Claude Code, batas keamanan diatur lewat settings dan permissions. CLAUDE.md menjelaskan aturan Vault, sedangkan .claude/settings.json membatasi akses file dan command.

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 di Obsidian tetap menjadi sumber kebenaran. Claude Code hanya membantu menyortir, merangkum, membuat draft, dan memverifikasi.

Mulai dari struktur kecil

Jangan membuat terlalu banyak kategori di awal.

mkdir -p inbox daily projects content-ops snippets templates scripts archive private
FolderFungsiPekerjaan aman untuk Claude Code
inbox/catatan mentah dan Web Clippermembuat dan memilah
daily/daily logs dan working memorymembuat, menambah, merangkum kemarin
projects/project handoff dan keputusanupdate handoff
content-ops/ide artikel, CTA, publishingmerapikan draft dan link
snippets/command dan contoh kodemenambah konteks dan tag
templates/template Obsidianbaca saja, edit perlu persetujuan
archive/catatan selesaijangan edit
private/data pribadi atau rahasiajangan baca

Struktur ini langsung mendukung pekerjaan nyata. Daily logs membawa task yang belum selesai. Project handoff menjelaskan goal, status, next action, dan risk. Snippets menyimpan command yang bisa dijalankan, versi dependency, dan failure example. Content operations memeriksa official links, internal links, /products/, dan /training/.

Tambahkan CLAUDE.md

Letakkan file ini di root 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 .`.

Pitfall umum adalah prompt “rapikan Vault saya”. Claude Code akan menebak folder, heading, dan tag. Tebakan itu bisa terlihat rapi, tetapi merusak search, Graph view, dan backlink.

Batasi permissions

Buat .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 *)"
    ]
  }
}

Konfigurasi ini memberi ruang untuk pekerjaan rutin, tetapi tetap meminta konfirmasi untuk template, Git, dan WebFetch. Jangan memakai bypass luas untuk Vault yang berisi data nyata.

Tiga template Obsidian

Daily template sebaiknya tipis.

---
date: "{{date:YYYY-MM-DD}}"
status: active
tags:
  - daily
---

# {{date:YYYY-MM-DD}}

## Today
- [ ]

## Learned
-

## Questions
-

## Links
- [[Weekly review]]

Project handoff harus membuat next action jelas.

---
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]]

Template content operations memasukkan monetization CTA sejak awal.

---
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

Untuk konteks tambahan, baca approval dan sandbox, documentation generation, dan content funnel audit. Arahkan pembaca solo ke products dan tim yang butuh rollout ke training.

Simpan sebagai 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}`);

Jalankan:

node scripts/audit-wikilinks.cjs .

Prompt yang aman:

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.

Pitfall umum

Pertama, membiarkan Claude Code mengubah .obsidian/. Setting plugin, tema, dan hotkey bukan catatan biasa.

Kedua, rename note di luar Obsidian. Bulk rename bisa memutus backlink.

Ketiga, YAML Properties tanpa kutip. Untuk internal link gunakan related: "[[Project name]]".

Keempat, daily note terlalu berat. Template yang tidak diisi setiap hari akan menjadi noise.

Kelima, content operations dianggap hanya menulis. Artikel publik juga butuh official links, internal links, CTA, dan verification.

Hasil percobaan Masa

Di Vault uji Masa, hasil terbaik muncul dari dua workflow: memindahkan unfinished tasks ke daily log berikutnya dan menjalankan audit link sebelum publikasi. Eksperimen terburuk adalah meminta Claude Code “bersihkan seluruh Vault”; hasilnya terlalu banyak tag dan heading baru. Permissions yang sempit, template ringan, dan audit Node membuat workflow lebih stabil.

#claude-code #obsidian #pkm #markdown #automation #second-brain
Gratis

PDF gratis: cheatsheet Claude Code

Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.

Kami menjaga datamu dan tidak mengirim spam.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.