write_note
Write content to a markdown note at a specified path, with optional YAML frontmatter and choice of overwrite, append, or prepend mode. Automatically creates missing parent directories.
Instructions
Writes content to a note. Pass { path, content } and optionally frontmatter (object) and mode (overwrite|append|prepend, default overwrite). Returns { root, path, message }. Creates parent directories automatically.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/note-tools.ts:70-108 (handler)Main handler function for the write_note tool. Constructs the tool object with name, description, input schema, and async handler that validates args, calls fileService.writeNote(), and returns a success/error response.
function makeWriteNoteTool(container: ServiceContainer): ToolHandler { return { name: "write_note", description: "Writes content to a note. Pass `{ path, content }` and optionally `frontmatter` (object) and `mode` (`overwrite`|`append`|`prepend`, default `overwrite`). Returns `{ root, path, message }`. Creates parent directories automatically.", inputSchema: WriteNoteSchema, async handler(args): Promise<ToolResponse> { const services = requireServices(container); const { path, content, frontmatter, mode } = WriteNoteSchema.parse(args); log.info({ path, mode }, "write_note called"); try { await services.file.writeNote(path, content, frontmatter, mode); log.info({ path, mode }, "write_note complete"); return { content: [ { type: "text", text: JSON.stringify({ root: getRoot(container), path, message: `Note ${mode === "overwrite" ? "written" : mode + "ed"} successfully.`, }), }, ], }; } catch (err) { log.error({ err, path }, "write_note failed"); return { content: [{ type: "text", text: JSON.stringify({ root: getRoot(container), error: err instanceof Error ? err.message : String(err), possibleSolutions: ["Check the path is root-relative", "Ensure the path is not blocked (.obsidian, .git)", "Use read_note to confirm an existing note's path"], }) }], isError: true, }; } }, }; } - src/tools/note-tools.ts:61-68 (schema)Zod schemas for write_note input validation: WriteNoteSchema defines path (string), content (string), frontmatter (optional record), and mode (enum: overwrite/append/prepend, default 'overwrite').
const WriteModeSchema = z.enum(["overwrite", "append", "prepend"]); const WriteNoteSchema = z.object({ path: z.string().min(1, "path is required"), content: z.string(), frontmatter: z.record(z.string(), z.unknown()).optional(), mode: WriteModeSchema.optional().default("overwrite"), }); - src/tools/note-tools.ts:345-360 (registration)Registration function registerNoteTools that adds makeWriteNoteTool result to the global tool registry map.
export function registerNoteTools( registry: Map<string, ToolHandler>, container: ServiceContainer, ): void { const tools = [ makeReadNoteTool(container), makeWriteNoteTool(container), makePatchNoteTool(container), makeDeleteNoteTool(container), makeMoveNoteTool(container), makeReadMultipleNotesTool(container), ]; for (const tool of tools) { registry.set(tool.name, tool); } - src/services/file-service.ts:85-125 (helper)FileService.writeNote implementation. Handles atomic overwrite, append (concatenates new content after existing), and prepend (concatenates new content before existing), with frontmatter support via gray-matter.
async writeNote( relativePath: string, content: string, frontmatter?: Record<string, unknown>, mode: WriteMode = "overwrite", ): Promise<void> { log.info({ path: relativePath, mode }, "writeNote"); const newRaw = frontmatter ? matter.stringify(content, frontmatter as matter.GrayMatterFile<string>["data"]) : content; if (mode === "overwrite") { const fullPath = this.resolvePath(relativePath); await this.atomicWrite(fullPath, newRaw); return; } // For append/prepend, read existing content first (file may not exist yet) let existingRaw = ""; try { const fullPath = this.resolvePath(relativePath); existingRaw = await fs.readFile(fullPath, "utf-8"); } catch (err) { if ((err as NodeJS.ErrnoException).code !== "ENOENT") { throw err; } } const combined = mode === "append" ? existingRaw ? existingRaw + "\n" + newRaw : newRaw : existingRaw ? newRaw + "\n" + existingRaw : newRaw; const fullPath = this.resolvePath(relativePath); await this.atomicWrite(fullPath, combined); } - src/types.ts:154-160 (helper)TypeScript interface declaration for writeNote method on the FileService interface.
/** Create or overwrite/append/prepend to a note */ writeNote( path: string, content: string, frontmatter?: Record<string, unknown>, mode?: WriteMode, ): Promise<void>;