insert_at_heading
Insert content under a specific heading in an Obsidian note. Add text at the start or end of a heading section to organize notes effectively.
Instructions
Insert content under a specific heading in a note
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the note | |
| heading | Yes | The heading text to insert content under | |
| content | Yes | Content to insert | |
| position | No | Insert at start or end of the heading section. Default: end | end |
Implementation Reference
- src/index.ts:718-770 (handler)The core handler function that implements the tool logic: reads the note file, locates the specified heading, finds the end of the heading's section, inserts the provided content at the start or end of the section, and saves the updated file.async function handleInsertAtHeading(args: { path: string; heading: string; content: string; position?: "start" | "end"; }): Promise<string> { const fullPath = resolvePath(args.path); const position = args.position ?? "end"; if (!(await fileExists(fullPath))) { throw new Error(`Note not found at ${args.path}`); } const fileContent = await fs.readFile(fullPath, "utf-8"); const lines = fileContent.split("\n"); // Find the heading const headingPattern = new RegExp(`^#+\\s+${args.heading}\\s*$`); let headingIndex = -1; for (let i = 0; i < lines.length; i++) { if (headingPattern.test(lines[i])) { headingIndex = i; break; } } if (headingIndex === -1) { throw new Error(`Heading "${args.heading}" not found in ${args.path}`); } // Find the end of this section (next heading of same or higher level) const headingLevel = (lines[headingIndex].match(/^#+/) || [""])[0].length; let sectionEnd = lines.length; for (let i = headingIndex + 1; i < lines.length; i++) { const lineHeadingMatch = lines[i].match(/^#+/); if (lineHeadingMatch && lineHeadingMatch[0].length <= headingLevel) { sectionEnd = i; break; } } // Insert content if (position === "start") { lines.splice(headingIndex + 1, 0, "", args.content); } else { lines.splice(sectionEnd, 0, args.content, ""); } await fs.writeFile(fullPath, lines.join("\n"), "utf-8"); return `Successfully inserted content under heading "${args.heading}" in ${args.path}`; }
- src/index.ts:272-298 (schema)The tool's metadata and input schema definition in the tools array, used for tool listing and validation.name: "insert_at_heading", description: "Insert content under a specific heading in a note", inputSchema: { type: "object", properties: { path: { type: "string", description: "Path to the note", }, heading: { type: "string", description: "The heading text to insert content under", }, content: { type: "string", description: "Content to insert", }, position: { type: "string", enum: ["start", "end"], description: "Insert at start or end of the heading section. Default: end", default: "end", }, }, required: ["path", "heading", "content"], },
- src/index.ts:920-929 (registration)The switch case in the main tool call handler that routes calls to 'insert_at_heading' to the specific handler function.case "insert_at_heading": result = await handleInsertAtHeading( args as { path: string; heading: string; content: string; position?: "start" | "end"; } ); break;