Metadator is an Obsidian plugin that generates metadata (tags, description, title) for notes using the Anthropic Claude API. The user runs a command, the plugin sends note content to Claude, parses the JSON response, and writes the results into the note's YAML frontmatter.
bun install # Install dependencies
bun run dev # Watch mode with auto-rebuild
bun run build # Production build (runs check first)
bun run check # Run all checks (typecheck + biome)
bun run typecheck # TypeScript type checking only
bun run lint # Biome lint + format check
bun run lint:fix # Auto-fix lint and format issues
bun run format # Format code with Biome
bun run validate # Full validation (types, checks, build, output)
bun run version # Sync package.json version to manifest.json + versions.json
bun test # Run tests- src/main.ts — Plugin entry point. Registers the
generate-metadatacommand, loads/saves settings, migrates legacyupdateMethodvalues. - src/metadata.ts — Orchestrates metadata generation. Checks whether fields need updating, builds the prompt dynamically (omitting title when disabled), calls Claude, parses JSON from the response with regex (
/{[\s\S]*}/), and writes tags/description/title to frontmatter. - src/settings.ts —
MetadataToolSettingsinterface andDEFAULT_SETTINGS. Field names:anthropicApiKey,anthropicModel,tagsFieldName,descriptionFieldName,titleFieldName,enableTitle,truncateContent,maxTokens,truncateMethod,updateMethod, plus per-field prompt strings. - src/settingsTab.ts — Settings UI (
PluginSettingTab). Password-masked API key, model dropdown, toggles, and text inputs for field names and prompts. - src/utils.ts —
callClaude()(Anthropic SDK call withdangerouslyAllowBrowser: true),getContent()(content extraction and truncation),updateFrontMatter()(async writes viaapp.fileManager.processFrontMatter()).
Tests are colocated with source files in src/:
- src/main.test.ts — Plugin lifecycle tests
- src/metadata.test.ts — Metadata generation and parsing tests
- src/utils.test.ts — Utility function tests (truncation, Claude calls, frontmatter)
- src/test-preload.ts — Test mocks for Obsidian API
- scripts/validate-plugin.ts — Full plugin validation (typecheck + lint + build)
- version-bump.ts — Syncs version from
package.jsonintomanifest.jsonandversions.json
- User runs "Generate metadata for current note" command
generateMetadata()checks which fields need population based onupdateMethod- Content is extracted and optionally truncated via
getContent() callClaude()sends the prompt to the Anthropic API- Response JSON is extracted with regex and parsed
updateFrontMatter()writes each field viaprocessFrontMatter()
- Frontmatter updates use
app.fileManager.processFrontMatter()— notparseYaml/stringifyYaml - Token counting uses a regex that handles CJK characters, words, and punctuation:
/[\u4e00-\u9fa5]|[a-zA-Z0-9]+|[.,!?;,。!?;#]|[\n]/g - Truncation methods:
head_only(first N tokens),head_tail(80% start + 20% end),heading(outline + first paragraph per section) - Anthropic client is initialized with
dangerouslyAllowBrowser: truesince it runs inside Obsidian's Electron renderer - Tags are appended (deduped); description and title use update/keep logic based on
updateMethod
- build.ts — Bun's native bundler producing CommonJS output (
main.js) - Externals:
obsidian,electron - Production builds are minified; dev builds are not
main.jsis committed to the repo (required by Obsidian plugin distribution)
- Update
package.jsonversion - Run
bun run versionto sync manifest.json and versions.json - Commit and tag:
git commit -m "chore: bump version to X.Y.Z"thengit tag X.Y.Z - Push with tags — GitHub Actions creates the release
Pre-release: run bun run validate.
Enforced by Biome: 2-space indent, organized imports, git-aware VCS integration.