Catatan Obsidian "tumbuh sendiri" berkat AI. Cara membangun otak kedua
Biarkan AI membaca Vault Obsidian: menautkan, meringkas, merapikan catatan berserakan jadi otak kedua yang tumbuh sendiri.
Tengah malam jam 12, saya mengetik “command itu, apa ya namanya” ke kotak pencarian Obsidian.
Sebuah command shell 3 baris yang saya catat 2 tahun lalu. Saya yakin itu ada. Tapi di mana ia terkubur di antara lebih dari 500 catatan, sama sekali tak teringat. Akhirnya hari itu saya menyerah mencari, lalu googling sekali lagi.
Saya rasa ini bukan cuma saya.
Obsidian (aplikasi catatan) itu makin dipakai makin praktis. Tapi sekaligus, pasti makin berantakan. Log harian, catatan bacaan, potongan kode, ide artikel, notula rapat. Semuanya menumpuk sebagai file Markdown, dan setengah tahun saja, ia jadi “rumah sampah khusus milikku yang susah dicari”.
Maka yang mulai saya kerjakan adalah membiarkan AI membaca Vault (tempat menyimpan catatan), lalu mengoper sekitar separuh perapiannya. Menempelkan link, membuat ringkasan, memungut catatan yang tersesat. Kalau ini diputar sedikit demi sedikit tiap hari, catatan yang tadinya berserakan mulai saling tersambung sendiri, dan benar-benar mulai terasa seperti “otak kedua”. Hari ini saya ceritakan itu.
Memangnya, “catatan tumbuh” itu apa?
Catatan biasa, puncaknya adalah saat ditulis. Setelah itu cuma dilupakan.
Tapi Obsidian punya fitur menyambung catatan lewat penulisan [[nama catatan]] (namanya Wikilink), dan makin disambung, ia makin jadi seperti satu peta. Dari catatan “error tipe TypeScript” bisa lompat ke “cerita Docker yang dulu bikin pusing”, lalu dari sana tersambung ke “refleksi penanganan insiden bulan lalu”. Sensasi titik jadi garis, garis jadi bidang.
Masalahnya, kalau penyambungan ini dikerjakan manusia, terlalu repot sampai tidak bisa berkelanjutan.
Di sini saya serahkan ke AI. Tepatnya, sebagai partner saya pakai alat bernama Claude Code. Ini sebenarnya AI untuk menulis kode, tapi intinya bisa dipakai sebagai “petugas yang aman membaca-menulis folder yang penuh file Markdown”. Keunggulan local-first Obsidian (file disimpan di PC sendiri) tetap utuh, cuma repotnya perapian yang dioper ke AI. Inilah strategi hari ini.
Tapi, izinkan saya memaku satu hal di awal. Memberi izin edit seluruh Vault ke AI, jangan pernah dilakukan.
.obsidian/ (folder setelan), artikel yang sudah dipublikasi, catatan pribadi macam kontrak, API key—tidak ada alasan untuk dibaca AI. Karena itu saya menjalankannya dengan prinsip “membaca agak lebar, menulis super hati-hati”. Ini persis cara berpikir yang dulu saya tulis di Cara membuat “pijakan” untuk mendelegasikan pekerjaan ke AI, intinya pasang roda bantu dulu baru disuruh lari.
Ampuh di situasi-situasi ini (3 contoh)
Karena teori abstrak susah tersampaikan, ini 3 momen di mana saya benar-benar merasa “wah, ampuh nih”.
Pertama, log harian pagi. Tiap pagi, saya suruh AI membaca catatan kemarin lalu minta “pindahkan cuma tugas yang belum selesai ke hari ini, dan mampatkan pelajaran kemarin jadi 3 baris”. Hasilnya, catatan yang diri-saya-kemarin biarkan berantakan, keluar dalam bentuk yang bisa digerakkan oleh diri-saya-hari-ini. “Ah, ini yang kemarin bikin mentok” langsung teringat sekejap. Orang yang menerima estafetnya adalah diri sendiri di masa depan.
Kedua, penyelamatan potongan kode.
Soal “command 2 tahun lalu” tadi. Kalau command yang pernah jalan saya lempar ke folder snippets/, AI akan menambahkan sendiri kalimat penjelasan “ini command untuk apa?” plus link ke catatan lain yang terkait. Command telanjang berubah jadi “catatan yang benar” yang bisa ditemukan lewat pencarian.
Ketiga, persiapan ide artikel.
Di hari menulis blog, saya tunjukkan buku ide di folder content-ops/ ke AI lalu tanya “artikel ini, bisa di-internal-link ke artikel lama yang mana?”. Kadang ia menarik keluar artikel setengah tahun lalu yang bahkan saya sendiri lupa, dan ini diam-diam ampuh. Itu, momen titik bertemu titik.
Tiga kesalahan yang pernah saya bikin
Mungkin di sini inti sebenarnya. Beberapa minggu pertama, Vault saya diobrak-abrik habis oleh AI. Saya buka jujur saja.
Pertama. Saya langsung minta “rapikan” seluruh Vault. Ini yang paling parah. AI mencoba “dengan baik hati” merapikan bahkan catatan tak jelas dari 2 tahun lalu, lalu menumbuhkan banyak sekali tag dan judul seenaknya. Graph view (layar yang memvisualkan sambungan catatan) jadi hutan penuh tag asing. Maksud catatan lama itu tak mungkin dipahami AI. Tapi ia tetap bergerak berdasar tebakan. Sejak itu, target selalu saya batasi ke satu folder saja.
Kedua. Saya biarkan AI mengganti nama catatan seenaknya.
“Bikin judulnya lebih jelas ya.” Dengan ini, link [[nama catatan lama]] putus serentak. Obsidian, kalau kamu sendiri yang ganti nama, link-nya ikut menyesuaikan, tapi kalau AI eksternal mengganti nama file secara borongan, penyesuaian itu tidak berlaku. Tumpukan mayat link mati. Sekarang “rename wajib konfirmasi manusia” jadi hukum besi.
Ketiga. Saya membiarkan private/ terbaca.
Ini bukan sekadar jantung berhenti sedetik. Folder berisi catatan nominal kontrak, gara-gara saya malas menyetel izin, ada dalam keadaan bisa dibaca AI. Kecelakaan memang tidak terjadi, tapi itu sama seperti menyuruh anak baru menyentuh DB produksi dengan tangan kosong. Kalau saja ditulis benar di deny (daftar tolak), kecelakaan mustahil terjadi sejak awal. Pelajarannya: yang salah adalah saya yang pelit menyetel.
Cara memulai: cukup taruh 3 file
Tidak susah. Cukup siapkan 3 hal tepat di bawah Vault.
Pertama, bagi foldernya. Kalau dari awal mengklasifikasi terlalu detail pasti ambruk, jadi kasar-kasar saja sudah cukup.
# Jalankan tepat di bawah Vault. Pisahkan saja: tempat dipakai harian, proyek, kerja publikasi, area terlindungi
mkdir -p inbox daily projects content-ops snippets templates scripts archive private
Peran tiap folder, dan sampai mana didelegasikan ke AI, saya bagi begini.
| Folder | Peran | Jangkauan untuk AI |
|---|---|---|
inbox/ | Penampung catatan mentah, kliping web | Baca dan buat baru |
daily/ | Log harian, catatan kerja | Buat, tambah, ringkas hari sebelumnya |
projects/ | Tugas berjalan, estafet | Buat, update, rapikan hal yang belum diputuskan |
content-ops/ | Ide artikel, internal link, cek publikasi | Rapikan draf, cek link |
snippets/ | Potongan kode dan cara pakai | Tambah penjelasan, rapikan tag |
templates/ | Template Obsidian | Prinsipnya edit setelah konfirmasi |
archive/ | Selesai, tersimpan | Dilarang edit |
private/ | Info pribadi, kontrak, rahasia | Membaca pun dilarang |
Berikutnya, taruh CLAUDE.md tepat di bawah Vault. Ini kertas berisi “aturan kami” untuk AI. Daripada berkhotbah filosofi panjang, lebih ampuh menulis singkat aturan input-output yang ingin dipatuhi.
# Aturan Obsidian Vault
## Peran
- Vault ini tempat menaruh log harian, estafet proyek, potongan kode, ide artikel.
- Bergeraklah supaya tetap berguna tanpa membaca private.
## Kebijakan folder
- `daily/`: buat dan update catatan harian dengan `YYYY-MM-DD.md`.
- `projects/`: pertahankan 1 lembar catatan estafet per kasus aktif.
- `snippets/`: simpan command yang jalan beserta latar belakang dan contoh kegagalannya.
- `templates/`: membaca bebas. Sebelum mengedit, wajib tanya dulu.
- `archive/` dan `private/`: jangan diedit. Isi private bahkan jangan diringkas.
## Aturan penulisan
- Internal link ditulis dalam format Wikilink `[[nama proyek]]`.
- Pasang properti YAML (status, dll.) di awal catatan.
- Satu paragraf tahan di dalam 5 baris.
## Aturan keamanan
- Rename catatan yang sudah ada, wajib konfirmasi dulu.
- Jangan ubah setelan `.obsidian/`.
- Sebelum edit borongan, keluarkan daftar file target lalu tunggu persetujuan.
- Setelah mengedit, wajib jalankan `node scripts/audit-wikilinks.cjs .`.
Yang terakhir paling penting. Lewat .claude/settings.json, ikat izin secara fisik. CLAUDE.md itu “permintaan”, tapi yang ini “kunci fisik”. Penjaga pintu agar kesalahan ketiga tadi tidak pernah terulang. Membaca agak lebar, menulis cuma di folder kerja, operasi berbahaya disegel total dengan deny. Detail setelannya lihat dokumentasi izin resmi.
{
"$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 *)"
],
"deny": [
"Read(./private/**)",
"Read(./**/.env)",
"Read(./**/.env.*)",
"Edit(./.obsidian/**)",
"Edit(./archive/**)",
"Write(./archive/**)",
"Bash(rm *)",
"Bash(del *)"
]
}
}
Setelah menaruh 3 lembar ini, tinggal meminta. Triknya, jangan bilang “rapikan yang bagus ya”. Jangkauan, hasil akhir, larangan, sampai verifikasi—tentukan semua tiap kali.
Baca daily/2026-06-04.md dan projects/site-refresh.md.
Buat daily/2026-06-05.md berdasar templates/daily.md.
Tugas yang belum selesai, estafetkan cuma yang penanggung jawabnya masih diriku sendiri.
.obsidian/ dan archive/ dan private/ jangan disentuh.
Setelah selesai mengedit, jalankan node scripts/audit-wikilinks.cjs . lalu laporkan hasilnya.
Singkat, tapi input, output, jangkauan larangan, dan command verifikasi semuanya masuk. Berkali-kali lipat lebih bisa diulang hasilnya dibanding “yang bagus ya”.
Penjaga pintu sentuhan akhir: cek link mati secara mekanis
Kalau AI eksternal disuruh mengedit file, kadang Wikilink rusak. Mata manusia bakal melewatkannya. Maka di akhir, sisipkan skrip yang secara mekanis menyisir link yang rusak. Simpan ini sebagai scripts/audit-wikilinks.cjs.
#!/usr/bin/env node
// Skrip penjaga pintu yang menyisir internal link ([[...]]) yang rusak/ambigu di dalam Vault
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("Ditemukan internal link yang rusak/ambigu:");
for (const problem of problems) console.error(`- ${problem}`);
process.exit(1);
}
console.log(`OK: ${markdownFiles.length} berkas Markdown di ${vaultRoot} sudah diperiksa`);
Menjalankannya cuma ini.
node scripts/audit-wikilinks.cjs .
Kalau semua link hidup, keluar OK. Kalau ada yang putus, ia memberi tahu dalam daftar: link mana di file mana yang mati. Menjalankan ini tepat setelah AI merapikan, itulah penutup harian saya.
Oh ya, untuk spesifikasi akurat sisi Obsidian (Daily notes, Templates, Properties, internal link), rujuklah bantuan resmi Obsidian. Memahami spesifikasi kapal induk sendiri sebelum mendelegasikan ke AI, akan menghindarkanmu dari memberi instruksi aneh.
Hasil setelah saya coba sendiri
Selama 3 bulan, saya putar Vault saya dengan mekanisme ini.
Yang paling ampuh, ya tetap “estafet log harian” dan “audit link sebelum publikasi”. Begitu pagi-pagi AI saya suruh meringkas hari kemarin, mesinnya jelas lebih cepat menyala. “Oh, diri-saya-kemarin berhenti di sini”, langsung terbaca sekilas, jadi selagi menyeduh kopi, kepala sudah beralih ke mode hari ini. Sejak menyisipkan audit link, malam-malam pucat gara-gara “ah, internal link-nya putus” setelah mempublikasi artikel jadi nol. Kalau diangkakan, sebelum audit saya mempublikasi link mati 2–3 kali sebulan, sekarang nol.
Satu lagi, ada produk sampingan tak terduga. Dengan adanya asumsi “tiap hari disentuh AI”, cara saya sendiri menulis catatan berubah. Karena ingat nanti akan dibaca mesin, saya jadi otomatis memasang status: atau menambah satu baris konteks bahkan di catatan mentah. Niatnya merapikan demi AI, ujung-ujungnya yang paling mudah dibaca justru diri saya, manusianya.
Sebaliknya, kali saya menyuruh merapikan seluruh Vault sekaligus di awal, itu jelas gagal. AI terlalu menebak makna catatan lama, dan tag serta judul malah bertambah jadi berantakan. Kesimpulannya sederhana: makin menjaga 3 poin “jangkauan izin sempit, template tipis, audit Node di akhir”, makin berhasil.
Yang menarik, command 2 tahun lalu yang setengah tahun lalu mustahil saya ingat, kini bisa saya capai dalam 5 detik. Link yang AI tempelkan tekun-tekun, saya tinggal menelusurinya. Catatan, benar-benar mulai jadi otak.
Penutup
Sosok asli “catatan tumbuh sendiri” bukanlah sihir. Membaca lebar, menulis sempit, di akhir periksa ulang dengan mesin. Cuma menjadikan hal biasa ini sebuah mekanisme.
Yang dikerjakan ada 3. Bagi folder, tulis aturan di CLAUDE.md, lalu tutup operasi berbahaya secara fisik dengan .claude/settings.json. Sisanya, jangan bilang “yang bagus ya”, cukup minta dengan jangkauan yang dipersempit. Hari ini, mulailah dari satu folder daily/ dulu. Diri-kamu-besok akan jadi sedikit lebih ringan.
Yang ingin tahu lebih detail cara berpikir izin dan sandbox, silakan ke Desain persetujuan dan sandbox Claude Code. Template untuk dipraktikkan dan tempat konsultasi penerapan tim saya rangkum di daftar materi.
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.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Cara Menulis Instruksi agar Claude Code Hanya Mengubah Satu File
Dari kegagalan 'bikin lebih bagus' yang mengubah 40 baris: template brief Claude Code yang menyatukan scope, verifikasi, dan rollback.
Pulih dari permission denial Claude Code tanpa melemahkan guardrail
Ubah command Claude Code yang ditolak menjadi recovery prompt dengan alasan, alternatif aman, proof command, dan kriteria retry.
Claude Code Harness Smoke Test: loop bukti 15 menit sebelum mempercayai agen
Pemeriksaan Claude Code untuk scope, area terlarang, command bukti, URL publik, dan CTA pendapatan.