This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Flint — Spencer's personal Obsidian plugin (TypeScript + React 19, esbuild via Bun). AI chat over the vault (read-only RAG + tool-calling agent mode), web-clip ingest/organize, triage, daily dashboards.
- Build:
bun run build(runstsc -noEmitthen esbuild; must exit 0 before any deploy) - Test:
bun test(all),bun test <file-substring>(one file) - Deploy:
just --yes flint_deploy(build →just vault_syncpull → copymain.js/manifest.json/styles.cssinto../flint-main/.obsidian/plugins/flint/→ sync push →obsidian plugin:reload id=flint).just flint_deploy_shotadds a desktop screenshot.
- NEVER write the deployed
data.json(in the vault plugin dir). The running app holds settings in memory and overwrites file edits. Settings changes ship as code: bumpSETTINGS_VERSIONand extendloadSettingsFromRawinsrc/settings.ts— migration decisions run on the RAWloadData()blob, before defaults merge. - The live vault's WSL copy is
../flint-main/; never touch the Windows-side vault path directly (read-only checks via/mnt/c/Users/MLPC/Documents/Flint Main/are fine). - All vault writes go through Obsidian
Vault/FileManagerAPIs (neverfs); moves viafileManager.renameFileso backlinks survive. - Agent security invariants (don't weaken): no delete tool; mutating tools confirm via Apply/Skip; moves validated by exact match against the live folder allowlist (
src/agent/vault-tree.ts); tool results framed as untrusted; proposal bodies render as plain text, neverMarkdownRenderer; LLM-suggested destinations are only trusted via allowlist membership (src/triage/organize-parse.ts).
- Obsidian Sync races
plugin:reload: after the sync push, the Windows app pulls on its own schedule — verify the newmain.jslanded Windows-side (grep for a new-code marker) or wait ~20 s before reloading, else the OLD build reloads. - The
obsidianshim sometimes loses stdout over WSL interop — route through a.cmdin Windows Temp viacmd.exe /c(see the globalobsidianskill). obsidian dev:screenshotcan return stale frames; confirm UI state withobsidian eval(e.g.app.plugins.plugins.flint.manifest.version) before debugging from a screenshot.
- The real
obsidianpackage is types-only;test/obsidian-mock.tsreplaces it viamock.module— import it FIRST in every test file, thenawait import(...)the code under test. test/fake-vault.tscreateFakeApp(files, {folders})provides vault + folder tree +fileManager+metadataCache.- Provider request bodies for plain string-content messages must stay byte-identical (regression tests in
test/providers-tools.test.ts).
- UI copy: sentence case ("Apply selected", not "Apply Selected"); no
innerHTML; icons strokecurrentColor. - Release bump:
manifest.jsonversion + matching entry inversions.json.