update_frontmatter
Update frontmatter in markdown files by adding, modifying, or removing keys. Control whether changes merge with or replace existing content.
Instructions
Sets and/or removes frontmatter keys. Pass { path, fields?, remove?, merge? }. fields sets key-value pairs (null is a real value, pass-through to schema validation). remove is a list of keys to delete. merge (default true) merges with existing frontmatter; false replaces all fields. Returns { root, path, frontmatter }.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/frontmatter-tools.ts:78-125 (handler)The main tool handler for update_frontmatter. Parses input (path, fields, remove, merge), delegates to frontmatter service's updateFields, re-reads the note, and returns updated frontmatter.
function makeUpdateFrontmatterTool(container: ServiceContainer): ToolHandler { return { name: "update_frontmatter", description: "Sets and/or removes frontmatter keys. Pass `{ path, fields?, remove?, merge? }`. `fields` sets key-value pairs (null is a real value, pass-through to schema validation). `remove` is a list of keys to delete. `merge` (default true) merges with existing frontmatter; false replaces all fields. Returns `{ root, path, frontmatter }`.", inputSchema: UpdateFrontmatterSchema, async handler(args): Promise<ToolResponse> { try { const services = requireServices(container); const { path: notePath, fields, remove, merge } = UpdateFrontmatterSchema.parse(args); log.info( { notePath, fieldCount: Object.keys(fields).length, removeCount: remove.length, merge, }, "update_frontmatter called", ); await services.frontmatter.updateFields(notePath, fields, merge, remove); const updatedNote = await services.file.readNote(notePath); log.info({ path: notePath }, "update_frontmatter complete"); return { content: [ { type: "text", text: JSON.stringify( { root: getRoot(container), path: notePath, frontmatter: updatedNote.frontmatter }, null, 2, ), }, ], }; } catch (err) { log.error({ err }, "update_frontmatter failed"); return { content: [{ type: "text", text: JSON.stringify({ root: getRoot(container), error: err instanceof Error ? err.message : String(err), possibleSolutions: ["Check the path with list_directory", "Verify the file exists with read_note", "Ensure field values are valid YAML types"], }) }], isError: true, }; } }, }; } - src/tools/frontmatter-tools.ts:59-76 (schema)Zod input schema for update_frontmatter: path (required), fields (optional key-value pairs), remove (optional string array), merge (optional boolean, default true).
const UpdateFrontmatterSchema = z.object({ path: z.string().describe("Root-relative path to the note."), fields: z .record(z.string(), z.unknown()) .optional() .default({}) .describe("Key-value pairs to set in the frontmatter. `null` is a valid value (not a delete sentinel) — use `remove` to drop keys."), remove: z .array(z.string()) .optional() .default([]) .describe("Keys to delete from the frontmatter. Runs after the merge/replace step, so a key in both `fields` and `remove` ends up removed."), merge: z .boolean() .optional() .default(true) .describe("If true (default), merge with existing frontmatter. If false, replace all fields."), }); - src/tools/frontmatter-tools.ts:180-193 (registration)Registration function that adds update_frontmatter (along with other frontmatter tools) to the tool registry.
export function registerFrontmatterTools( registry: Map<string, ToolHandler>, container: ServiceContainer, ): void { const tools = [ makeGetFrontmatterTool(container), makeUpdateFrontmatterTool(container), makeManageTagsTool(container), ]; for (const tool of tools) { registry.set(tool.name, tool); } } - Helper service method called by the handler. Reads the note, merges/replaces frontmatter fields, deletes keys in 'remove', stringifies and atomically writes back.
async updateFields( notePath: string, fields: Record<string, unknown>, merge = true, remove: string[] = [], ): Promise<void> { log.info( { path: notePath, merge, fieldCount: Object.keys(fields).length, removeCount: remove.length, }, "updateFields", ); const note = await this.file.readNote(notePath); const { frontmatter, content } = note; const updatedFrontmatter: Record<string, unknown> = merge ? { ...frontmatter, ...fields } : { ...fields }; for (const key of remove) { delete updatedFrontmatter[key]; } const newRaw = this.stringify(updatedFrontmatter, content); const fullPath = this.file.resolvePath(notePath); await this.file.atomicWrite(fullPath, newRaw); log.info({ path: notePath, merge }, "updateFields complete"); } - src/types.ts:224-229 (schema)TypeScript interface definition for the updateFields method on FrontmatterService, used by the tool handler.
updateFields( path: string, fields: Record<string, unknown>, merge?: boolean, remove?: string[], ): Promise<void>;