Skip to content

2.14.0

Latest

Choose a tag to compare

@quickadd-release-bot quickadd-release-bot released this 02 Jul 00:54

This is the biggest QuickAdd update yet. The AI Assistant can now act as an agent that works in your vault - searching, reading, and (only with your approval) writing notes through tools you hand it. Prompts now write real typed properties - numbers, checkboxes, sliders, multi-select lists, date & time - instead of red untyped text. Capture can target notes by their properties, let you pick the heading at capture time, and keep newest-first logs that sort themselves. A new "New note from template" command runs any template without configuring a choice, {{CLIPBOARD}} now captures images, and the plugin itself is ~4x smaller, so Obsidian starts faster on every device - plus a security-hardening pass and a long list of quality-of-life fixes.

Note

Seeing this inside Obsidian for the first time? That's a fix, not a new habit. If you installed QuickAdd after late 2025, the default "Announce updates" level (Major versions only) never matched QuickAdd's releases - features ship as minor bumps (2.13 → 2.14), so those installs never got release notes in-app. Feature releases now announce as intended; patch releases stay quiet. You can change the level (or turn announcements off) in QuickAdd's settings.


🤖 Your AI assistant can now work in your vault

Until now, ai.prompt was one-shot: the model answered blind, with no way to look anything up. New in this release, a user script can hand the model tools - and it uses them in a loop until it has an answer. Ask "which books did I rate 5 stars this year?" and the agent actually searches your reading log, opens the notes, and answers from what it found:

module.exports = async ({ quickAddApi }) => {
  const agent = quickAddApi.ai.agent({
    model: "gpt-5",
    system: "You are a vault librarian. Ground every claim in the user's notes.",
    tools: { ...quickAddApi.ai.tools.vault({ only: ["read_note", "search_notes"], allowedRoots: ["Reading Log"] }) },
    stopWhen: quickAddApi.ai.stepCountIs(20),
  });
  const { text } = await agent.generate({ prompt: "Which books did I rate 5 stars this year, and what did I say about them?" });
  return text;
};

An AI agent searching the vault, asking for approval, and writing to the journal

  • Built-in tool groups you opt into: ai.tools.vault() (read_note, list_notes, search_notes, get_property_values - plus write tools create_note, append_to_note, insert_under_heading), ai.tools.workspace() (active note, selection), and ai.tools.system() (date). Or define your own with ai.tool({ description, inputSchema, execute }).
  • Structured output: agent.generate({ prompt, schema }) returns a validated JSON object, not prose - perfect for feeding a template.
  • Works across OpenAI, Anthropic, and Gemini providers (and OpenAI-compatible local servers).

Safety is layered in, because an agent in your vault should earn its trust:

AI tool confirmation modal

  • The agent only ever has the tools you explicitly hand it - there are no ambient capabilities.
  • Write tools pop a confirmation modal that says in plain language what the call will touch, with Deny as the focused default. A new "Confirm AI tool calls" setting (default: Destructive tools only) governs this.
  • allowedRoots fences a tool group to specific folders, so an agent can't surface notes outside them - enforced across every read tool.
  • Step and size caps bound the loop, and deliberately risky tools (delete, run choice, apply template) are not shipped in this first version.

One honest caution for script authors: the model chooses tool calls, and note content it reads can steer it. Treat tool results as untrusted input - the docs cover the details.

🪶 QuickAdd is ~4x smaller - Obsidian starts faster

QuickAdd's bundle went from 4.4 MB to 1.2 MB. Obsidian loads and parses a plugin's entire code at startup, so you feel this on every single launch - especially on mobile.

The weight was a bundled OpenAI-specific tokenizer, which was only ever accurate for some of the providers QuickAdd supports. Token counting is now a fast local estimate: scripts should use the new ai.estimateTokens(text) (the old countTokens still works as an alias), and chunked AI prompts plan with the estimator and automatically re-split if the provider says a chunk is too big.

🏷️ Prompts that write real typed properties

If you've ever had a template produce a red, "invalid" property - a number stored as text, a list crammed into one string - this section is for you. Format syntax placeholders can now declare their type, get the right input widget, and write properly typed Obsidian properties:

---
rating: {{VALUE:rating|type:number|min:1|max:10}}
finished: {{VALUE:finished|type:checkbox}}
genres: {{VALUE:fantasy,sci-fi,history|multi}}
started: {{VDATE:started,YYYY-MM-DDTHH:mm|time}}
---

Run that book template and you get a numeric prompt, a true/false picker, a multi-select, and a date picker with a time control:

Multi-select prompt from format syntax

…and the created note's Properties panel shows a real Number, Checkbox, List, and Date & time. Nothing red:

The resulting typed Properties panel

  • Sliders: {{VALUE:rating|type:slider|min:1|max:10|step:1|default:5}} shows a drag slider with a synced number field - ratings and priorities become one drag, even on mobile.

    Slider prompt

  • {{FIELD}} goes multi-select: {{FIELD:topic|multi}} gathers every topic value across your vault and lets you check several - written as a real YAML list.

  • Inherit metadata from the note you're in: {{FIELD:project|default-from:active}} pre-fills the prompt with the active note's own project value. Capture a task from inside a project note and its project property is already filled in.

  • |type:text closes the inverse trap: it quotes the value so 0042 stays text instead of silently becoming the number 42.

  • Scripts get this for free: a macro that hands QuickAdd an array or object for a frontmatter field now writes a real List/object property out of the box - no beta toggle. The popular Movie & Series script finally produces clickable cast/genre/director link lists instead of one broken red string (#662).

  • Multi-select links: |multi:linklist wraps each pick as a [[wikilink]]; |multi|custom lets you add off-list values.

🎯 Capture to notes by what they are, not where they live

Capture's "Capture to" field now accepts a property: target. Set it to property:status=reading and the note picker only lists notes whose frontmatter says so:

Property-filtered capture picker

A reading log becomes one choice: Capture to property:status=reading, format {{DATE}} - {{VALUE:quote}}. Trigger it while reading, and the picker shows exactly your in-progress books - no more maintaining a folder just so a capture can find the right notes.

  • property:type (no value) lists every note that has a type property.
  • Matching is case-insensitive and list-aware: Status: Reading and status: [reading, favorite] both match.
  • Narrow further with pipe filters - property:type=draft|folder:Notes, plus |tag:, |exclude-folder:, |exclude-tag:, |exclude-file:.
  • The value can itself be a token that resolves at run time: property:status={{VALUE}}.

📌 Capture lands exactly where you want

Two placement upgrades that finally unlock classic workflows:

Pick the heading when you capture. "After line…" gains a Choose heading when capturing toggle: instead of hard-coding a target line in the choice, QuickAdd reads the note at capture time and shows a dropdown of its actual headings. Project notes with changing sections stop needing one choice per section:

Runtime heading picker

Ordered sections: logs that sort themselves. "Create line if not found" gains an Ordered placement. When your insert-after heading (say ## {{DATE:YYYY-MM-DD}}) doesn't exist yet, QuickAdd creates it at its sorted position among sibling headings - by date, number, text, or even semver:

Ordered sections in a newest-first daily log

The newest-first daily log - impossible with one capture until now - just works: your pinned intro stays on top, each new day's section is created below it and above older days, and repeat captures the same day find the existing heading instead of duplicating it (#481). The same mechanism keeps a changelog sorted with 1.10.0 above 1.9.0.

Also in this area: when a capture opens the target note afterwards, the cursor now lands right after what you captured instead of at the top of the file (#348) - keep typing exactly where the text landed.

📎 {{CLIPBOARD}} captures images too

Copy a screenshot, run your usual {{CLIPBOARD}} capture, and QuickAdd now saves the image as a vault attachment (following your Obsidian attachment settings) and embeds it:

Clipboard image capture

Text on the clipboard behaves exactly as before - one capture choice now handles both. Repeated {{CLIPBOARD}} tokens in one capture reuse the same saved attachment.

📄 Templates without the busywork

  • "New note from template" - a new command (and a row in the Run QuickAdd picker) that lists every template in your template folder(s), asks for a name, and creates the note. You no longer need one Template choice per template file; the folder is the menu (#1023).

  • Multiple template folders: Settings → Templates & Properties now takes a list of folders - a personal Templates plus Work/Templates, all feeding suggestions. Your old single folder migrates automatically (#1170).

  • Search existing notes before creating. The name prompt can now search while you type: matching notes (and unresolved [[wikilink]] targets) appear above an explicit "Create new note" row. Typing "Alice" surfaces People/Alice.md before you create "Alice 1" (#184).

    Discovery-first note creation

  • Format syntax in the template path: Templates/{{VALUE:collectionName}} Template.md prompts once and picks the matching template - one choice serving a whole family of templates (#620).

  • One "New note location" dropdown replaces four tangled toggles in the Template builder: Obsidian default, specific folder, same folder as current file, or ask each time - and switching modes no longer looks like it deleted your folder list (#1131).

  • Copy link to clipboard: Template choices (and now Capture choices too) can put a wikilink to the created/captured note on your clipboard - paste it into your reading list, daily note, or a chat (#600).

🔗 Links that keep your indexes up to date

The "Append link" feature grew from one behavior into a small routing system:

  • Append to a specified note: every note a choice creates can register itself in an index note or MOC - [[The Pragmatic Programmer]] lands at the bottom of Reading MOC.md automatically, while you stay wherever you were working (#146).

  • Append into a frontmatter property: name a property (e.g. meetings) and the link is written into that property on the active note as a real list item - create a meeting note from a project hub and the hub's meetings property collects it. Handles create/convert/require-list modes, via Obsidian's own frontmatter API (#768).

    Append link into a frontmatter property

  • Embed works with every placement: Link type = Embed is now honored for New line, End of line, and After selection - not just Replace selection. ![[2026-07-02 Standup]] on its own line in your daily note renders the meeting inline (#1422).

🔎 Pickers you can actually read

  • Recent notes first: capture note pickers now sort like the Quick Switcher - this session's notes, then your recents, then everything else predictably - instead of surfacing whatever sorted first in the vault registry (#745, #539).

  • Titles, not UUIDs: file pickers label notes by frontmatter title (then first heading, then filename). Zettelkasten vaults where every row read 202606181045.md become legible - search still matches the real path (#491).

  • Compound filters and multi-picks: folder:Goals|folder:Projects|tag:active|exclude-folder:Archive scopes a picker to exactly "active work notes in either folder", and {{FILE:People|multi|link}} picks several people at once, written as a YAML list of wikilinks (#528, #467). The Capture To field shows live green/red feedback as you type filter syntax.

    Multi-file picker with filters

  • Icons for your choices: every choice type gets a sensible default icon in the picker and on its command - including the mobile toolbar, which used to show ? for every QuickAdd button. Override per choice with any Lucide icon name (#428, #766).

    Choice picker with icons

✨ New format tokens & prompt upgrades

  • {{FILE:People}} opens a picker over a folder's notes - |link for a wikilink, |path for the vault path, plus |multi, |custom, |label:, and tag/folder filters. Your "metadata folders" (People/, Projects/) stop drifting into inconsistent retyped names (#933, #1159).
  • {{FOLDER}} resolves to the folder the note is being created in ({{FOLDER|name}} for just the last segment) - let the destination drive file names and breadcrumbs (#1258).
  • {{linksection}} links to the heading your cursor is under: capture a task out of a long note and the backlink is [[Project Plan#Tasks]], not the top of a 2,000-line file (#387).
  • Date snapping: |startof: / |endof: with year, quarter, month, week, isoweek, day on {{DATE}} and {{VDATE}}. A weekly planner named {{VDATE:d,gggg.MM.[Wk]w|startof:week}} finally files a month-straddling week under the right month - one date prompt, snapped in the filename, day-accurate in the heading (#511).
  • Named suggesters: {{VALUE:Personal,Work,Errand|name:category}} - pick once, reuse the answer anywhere with {{VALUE:category}}: file name, tags, and body from a single prompt (#148).
  • |trim strips stray whitespace per token - [[{{VALUE:title|trim}}]] stops mobile keyboards' trailing spaces from creating phantom duplicate notes.
  • Commas inside options: {{VALUE:"Blocked, waiting on reply",In progress,Done}} - quote an option to keep its comma (#239).
  • Tab indents in the multi-line prompt instead of jumping focus - nested checklists inside a capture prompt at last (#764). (Shift+Tab still moves focus out.)

⚙️ Automation that reports back

  • x-callback-url support: obsidian://quickadd URIs can carry x-success, x-error, and x-cancel callbacks. An Apple Shortcut can trigger a capture and learn the outcome - including the created note's path and a ready-made obsidian://open URL to jump to it. Off by default; enable Allow URI x-callback-url in settings; only shortcuts: and obsidian: callback schemes are permitted (#1070).

  • Run user scripts from a note's code block: a macro's user script can now live inside a ```js fence in a regular note - editable anywhere, including mobile, with your own prose around it. The script picker lists qualifying notes right beside your .js files (#1065).

    Script in a note code block

  • Headless runs fail fast: a CLI/URI run that needs a prompt it can't pre-answer now returns a clean {ok:false} error envelope with an actionable message in milliseconds, instead of hanging a terminal forever (#1428).

🛡️ Hardening & trust

An internal security audit drove a large hardening pass this cycle - proactive fixes, no known exploitation in the wild. Most users will notice nothing except stricter package imports and the disappearance of freeze-on-paste stalls, which is exactly the point:

  • Imported packages are contained to your vault and fully disclosed. A shared package can no longer write outside your vault or into .obsidian/; every bundled file that could run as code is flagged for explicit acknowledgement before Import unlocks - even one disguised as notes/helper.txt. Packages with colliding or divergent contents are refused outright. Honest packages import exactly as before.
  • Template and Capture writes are locked to your vault. File names built from tokens (or smuggled in via obsidian:// links, which any webpage can offer) can no longer traverse out of the vault or silently redirect a capture to a different note than the one you configured.
  • A whole class of freeze-on-paste bugs is gone. Seven-plus regular expressions that could lock Obsidian's UI for seconds-to-minutes on unlucky content were rewritten as linear-time scanners - proven byte-identical on millions of fuzz cases. A 400 KB clipboard paste that took ~11 seconds now takes ~2 ms.
  • Secrets live in Obsidian's secret storage, not data.json. User scripts can declare type: "secret" settings: masked input, OS-keychain-backed storage, never synced, never exported in packages. AI provider keys already worked this way - and the migration now retries until every old plaintext key is actually moved.
  • We also hardened the release pipeline itself (scoped, non-persisted release credentials; build provenance attestation), so the main.js you download is verifiably the one CI built from this repo.

⚠️ Behavior changes to know about

Honest disclosure - a few things now behave differently, almost all of them for the better:

  • Empty captures abort with a "nothing to capture" notice instead of inserting a blank line.
  • Copy-link actions honor your vault's link-format setting - Markdown-link vaults now get [text](path) where QuickAdd always emitted wikilinks.
  • Anonymous {{VALUE|default:X}} actually applies its default when you submit empty (previously only the named form did).
  • Generated note paths are stricter: ./.. segments abort, backslashes count as path separators, trailing dots/spaces are trimmed per segment.
  • trim, name:, and optional are reserved words in {{VALUE}} options (write |default:trim if you want the literal text).
  • Quoted options parse differently: a,"b",c now strips the quotes; a fully quoted "a, b" is one option, not two.
  • Appending a template to a .canvas/.base file is blocked - it used to corrupt the file's JSON.
  • Variable names starting with __qa. are reserved and refused in URI/CLI parameters and capture variable assignment.
  • Package files that previously imported may now be refused with an error if they do something the review screen can't honestly represent.

🐛 Fixes

A themed selection of the ~60 fixes in this release:

Capture & templates

  • Captured text no longer glues onto the next line when your format doesn't end in a newline - ## Log + a capture no longer produces new- existing corruption.
  • Multi-line "Insert after" targets are found on later runs instead of being re-created every capture - the target block no longer duplicates (#742); inline captures with multi-line targets abort clearly instead of writing garbage (#468).
  • Top-of-note insertion is frontmatter-aware - captures and apply-template no longer write above or into YAML properties (#647).
  • Task captures no longer add a stray blank line below the inserted task (#312).
  • Backslashes survive capture: \nabla and C:\Users\nadia are taken verbatim instead of being mangled into linebreaks (#527).
  • Template self-inclusion can't hang QuickAdd anymore, and preflight over dense {{TEMPLATE:…}} graphs went from exponential to linear - one pathological setup dropped from ~1M rescans to instant.
  • Appending a template to an existing note merges frontmatter instead of stacking a second --- block that displaced your properties.
  • The one-page input form finds prompts inside included templates, so questions appear up front instead of popping mid-run.
  • The multi-line prompt no longer doubles backslashes (C:\temp stayed C:\temp, not C:\\temp).

Prompts & pickers

  • A note named like a format token can't freeze Obsidian anymore ({{filenamecurrent}}.md was an infinite loop), and {{SELECTED}} no longer hangs when the selection contains itself (#1358).
  • Typos fail loudly: invalid |case: styles, unknown FIELD filters, and conflicting |name: definitions warn instead of silently doing nothing.
  • A batch of 18 prompt fixes: Tab no longer crashes an empty suggester, the math prompt submits with Cmd+Enter, unparseable dates warn, the one-page form auto-focuses and submits on Enter.
  • Suggester leaks fixed (per-keystroke Popper instances, per-row scroll listeners, tag-listener accumulation) - prompts stay fast no matter how many you open.
  • The date-format preview no longer corrupts month/day names ("March" previewing as "3arch").
  • Search highlighting aligns for Unicode note names (Turkish İ no longer shifts the highlight).

Choices & settings

  • Editing a choice keeps your scroll and cursor position - toggles no longer bounce you to the top of the form (#1130).
  • Editing a folder from a filtered/search view no longer deletes its hidden children on save, and configuring a nested choice no longer crashes with DataCloneError.
  • A duplicated choice id (from device sync) no longer blanks the whole settings page - QuickAdd self-heals on load.
  • Global Variables no longer lose data when clearing or duplicating a name mid-edit.
  • The update modal can be closed on iPhone - the X was hiding under the Dynamic Island (#635).

Macros & automation

  • {{MACRO:Name::member}} conflicts resolve gracefully again (a 2.12.1 regression), a macro referencing a deleted choice skips it with a message instead of crashing, and aborting inside a Conditional branch actually halts the macro.
  • One failing startup macro no longer blocks the rest, and command palette entries stay in sync when duplicating or deleting choices.
  • quickadd:run success envelopes carry a verified field - no more ok:true when no file was created.

AI assistant

  • Errors name your actual provider with the real error message - no more "Assistant is dead.", no more blaming OpenAI for a Gemini failure.
  • Chunked prompts keep their separators - long content no longer reaches the model with lines run together.
  • Agents on OpenAI no longer fail mid-loop after a tool call, and the assistant-command settings modal no longer opens blank for default/removed models.
  • Folder scoping is anchor-exact: scoping tools to Projects no longer also exposes ProjectsArchive/ and Projects 2024/.

🧰 For script & template authors

  • Secret settings: declare type: "secret" (optionally with a stable id) in a script's settings block - masked input, SecretStorage-backed, stripped from package exports:

    settings: {
      name: "Readwise Sync",
      options: {
        "API Key": { type: "secret", id: "api-key", placeholder: "Paste API key" },
      },
    }

    Secret setting input

  • New AI surface: ai.agent(), ai.tool(), ai.tools.vault()/workspace()/system(), ai.stepCountIs(), ai.hasToolCall(), ai.estimateTokens(text); ai.prompt/ai.chunkedPrompt accept assignToVariable, and chunkedPrompt takes maxChunkTokens.

  • Deprecation: ai.countTokens(text, model) still works but returns a provider-agnostic estimate and ignores model - switch to estimateTokens(text).

  • requestInputs gains number and slider input types (numericConfig/sliderConfig) plus an optional flag; checkboxPrompt takes a header argument; fieldSuggestions.getFieldValues filters across multiple folders.

  • Behavior change: executeChoice with an unknown choice name reports the error and returns instead of throwing - a script relying on the crash to stop a macro will now continue past the call.

  • Sharing code between scripts is now a documented pattern (one shared .js module + require() with a runtime-built path), and the Capture docs gained recipes for capturing one entry to multiple notes.


📚 Full documentation at quickadd.obsidian.guide. Found a bug or have an idea? Open an issue - and if QuickAdd saves you time, consider supporting development ❤️

Full commit-level changelog

2.14.0 (2026-07-02)

Bug Fixes

  • ai-tools: tool-confirm safety, agent progress feedback, and step accounting (#1414) (76ff8e4)
  • ai: close allowedRoots fence bypass + honest truncated flag in vault read tools (#1443) (9d718b1), closes #1432
  • ai: enforce allowedRoots confinement in workspace tools (#1432) (52c32c8)
  • ai: keep OpenAI assistant content as a string (9a8656c)
  • ai: provider modals, model discovery errors, and provider-neutral messaging (#1413) (b0f2c26)
  • append links to focused properties (d83ed68)
  • build folder-capture path without a double slash (#1307) (a7caab0)
  • capture,template: insertion targets, canvas/base guard, links, and feedback (#1412) (bc2c765)
  • capture: abort inline insert-after on a multi-line target instead of silently missing (#468) (#1370) (076d54b), closes #1333
  • capture: allow clean concurrent-edit merges (#1302) (a3774d6)
  • capture: allow empty scoped target creation (f0a72e6)
  • capture: clarify scoped target selection (b620325)
  • capture: find multi-line insert-after/before targets instead of duplicating them (#1333) (eaa489d), closes #742
  • capture: keep cursor after opened captures (#1392) (201e084)
  • capture: preserve literal backslash sequences in captured content (#1301) (02d77a2), closes #527 #527 #527
  • capture: scope ordered-search fence masking to the note body (8107456), closes #1404
  • capture: stop adding a blank line after a task-formatted insert-after capture (#1355) (5094b91), closes #312 #312 #312
  • choice-list: preserve folder children when editing from a filtered view (#1353) (9407060)
  • choices: assign unique default names for new choices (#1318) (#1319) (5e08337)
  • cli: abort non-interactive runs instead of hanging on engine prompts (#1428) (c529b22)
  • core: command registration, multi-folder UX, URI/CLI guards, and update announcements (#1410) (cc075ea)
  • core: resolve 7 deepsec correctness/robustness BUG findings (core data utilities) (#1437) (6a27141)
  • deepsec core-src BUG cluster (FILE-token collision, proto-key lookups, folder guard, null-deref) (#1442) (0846fba)
  • default frontmatter append handling to create or convert (fedb0dc)
  • deps: bump undici to 6.27.0 (a4ff987)
  • deps: patch vulnerable undici and js-yaml (3e38189)
  • example-scripts: three deepsec robustness/data-integrity fixes (#1465) (b7fcb04), closes #1431 #1454
  • field: remove two ReDoS regexes from inline-field parsing (#1444) (2e76914), closes #1439 #1128 #1439
  • field: wikilink-aware inline-field parsing + stop migration deleting code blocks (#1439) (87e71a0)
  • file-suggester: register one document scroll listener per instance instead of per row (#1309) (217fce1)
  • format: handle non-string trimmed values (1d6de9f)
  • format: resolve current-file/note tokens in one pass to stop rescan loops (#1358) (#1369) (7b61d91)
  • formatter: consume empty tokens without looping (#1303) (0ce7951)
  • format: token previews, value-syntax warnings, and field-token parsing (#1411) (0a519ef)
  • frontmatter-aware top insertion for capture and apply-template (#1334) (0af26f5), closes #647
  • guard template expansion against inclusion cycles (#1308) (e705d75)
  • gui: preserve choice-builder edit position by converting the ChoiceBuilder trio to Svelte (#1130) (#1330) (2681dc3)
  • gui: stop DataCloneError when configuring a choice nested in a folder or Macro (#1350) (7a7c780)
  • integrations: field-value suggestion filters and defaults (#1417) (6e36797)
  • macro: correct conditional abort, deleted-choice handling, and command validation (#1409) (85eb77c)
  • macro: harden user-script member access conflicts (#964) (#1326) (b0974df)
  • make the update modal closable on iPhone (#635) (#1327) (2b93029)
  • normalize generated note paths (1abfb03)
  • normalize generated path routing (6c0f428)
  • package-import: classify bundled scripts as critical (#1305) (477957f)
  • preflight: drain template includes in formatted paths (5f33c2d)
  • preflight: ignore global-injected template includes (c6c8915)
  • preflight: match template include stack semantics (4f377aa)
  • preflight: mirror template include depth (bb073a3)
  • preflight: scan capture template includes (42dc4aa)
  • preflight: skip multi capture filters as tag targets (19b52f8)
  • preserve frontmatter property key casing (c8e555b)
  • preserve property focus through choice suggesters (db6817d)
  • prompts: suggester crashes, input handling, preflight, and API robustness (#1415) (5f71ca9)
  • reject empty generated path segments (f41e7ff)
  • render list front matter as real properties out of the box (#662) (#1338) (725b284)
  • resolve Obsidian plugin review lint findings (#1426) (72d13da)
  • resolve Obsidian reviewer code-quality findings (#1320) (f9ddbfe)
  • security: align capture-target scope classifier with the write-path resolver + case-insensitive assignToVariable guard (#1458) (318b606), closes #1448 #1448
  • security: close package-import disclosure gap and asset-path collisions (#1445) (755e0fd)
  • security: contain attacker-injectable capture-target redirection (#1448) (f2b0c67)
  • security: contain Template/Capture file writes and package reads within the vault (#1460) (b4cb0f6), closes #1434 #1434
  • security: contain untrusted package-import paths to the vault (#1434) (de54299)
  • security: guard front matter assignment against prototype pollution (#1431) (ce837be)
  • security: kill five quadratic-regex DoS hazards over untrusted content (#1463) (f93a845)
  • security: kill quadratic ReDoS in VDATE token regex (#1462) (aec6151), closes #1455 #1455
  • security: linearize two main-thread ReDoS regexes (caseTransform + FIELD_VAR_REGEX_WITH_FILTERS) (#1455) (95826d3)
  • security: reject import packages with divergent same-id choices (#1453) (9c9655e)
  • security: reject unsafe package asset destinations (#1304) (af20b5f)
  • security: retry secret migration instead of stranding plaintext API keys (#1457) (1cccddb)
  • self-heal duplicate choice ids on load (blank settings page) (#1461) (12ba5a4), closes #each #1451 #1451
  • settings: global-variable data loss, package overwrite guard, and settings UX (#1416) (bd50f94)
  • six deepsec correctness fixes (chunk gluing, capture gluing, preflight double-exec, template fan-out, proto lookups, O(H²) links) (#1464) (5d31e84), closes #312 #1442
  • suggester: file-index reindex race + per-prompt tag-listener leak + suggester teardown (#1446) (62adb09), closes #-tag #-pre
  • suggesters: align Unicode highlight + remove two dead-code units (#1456) (9beb266)
  • template: merge frontmatter on template append (e14ff42)
  • template: preserve append value prompts (ff49fd8)
  • three deepsec data-integrity BUG fixes (collision non-termination, dropped imported child, prompt backslash corruption) (#1459) (4547b22), closes #799
  • three deepsec functional bugs (folder scoping, migration guard, date preview) (#1435) (3534cb1)
  • ui: resolve deepsec UI/settings BUG findings (suggester leaks, AI modals, provider migration) (#1438) (18d6186), closes #1413 pre-#1413 #1413

Features

  • add {{FILE:}} token to pick a file from a folder (#1357) (851978e), closes #933 #1159
  • add frontmatter append link placement (79d02ef)
  • ai: LLM tool/function calling — ai.agent() + built-in tools (#714) (#1372) (3d97a16), closes Hi#risk
  • append-link: choose Link type independently of Link placement (#1422) (f2f29f4)
  • capture: "Under heading…" write position with a runtime heading dropdown (#1348) (246b8c5), closes #738
  • capture: capture to an arbitrary frontmatter property (#466) (#1363) (507f9d4), closes #tag
  • capture: copy captured note links to clipboard (8495781)
  • capture: order note picker by recency like Quick Switcher (#745, #539) (275b959)
  • capture: ordered create-if-not-found location for reverse-chrono logs (#481) (#1365) (6838026)
  • capture: support clipboard image attachments (#1393) (4e7735b)
  • choice: support icons in picker rows (#1396) (3fa4330)
  • commands: icon for choice commands on the mobile toolbar (#766) (#1342) (6e6f959)
  • field: default {{FIELD}} from the active note's property (default-from:active) (#1430) (22fde1f), closes #1429 #1429 #1429
  • format: add {{linksection}} token linking to the current heading (#387) (72901e9), closes Note#Heading
  • format: add bounded slider value inputs (#1387) (dc14d4a)
  • format: add trim option for value tokens (2f2cefb)
  • format: date snap options |startof:/|endof: for {{DATE}} and {{VDATE}} (#511) (#1371) (d98904e)
  • format: named suggester reuse via {{VALUE:options|name:x}} (#148) (#1336) (3c10915)
  • format: support FIELD multi-select (#1391) (0ad9c97)
  • format: support Obsidian property types in format syntax (#757) (#1367) (463ed3e), closes #1357 #387 #621 Hi#severity #todo
  • formatters: add {{FOLDER}} token for file names and paths (#1328) (7db9033), closes #1258
  • improve file and note suggesters (4c98621)
  • linking: append file links to specified notes (88e7d9b)
  • macro: run a user script from a note's ```js code block (#1065) (#1341) (7428dff)
  • prompt: insert tab character in multi-line input prompt (#764) (f04aad2)
  • template: add discovery-first note creation (#1397) (da2f6aa)
  • template: copy created note link (#1384) (5991a0e)
  • template: replace folder-location toggles with a single dropdown (#1131) (#1344) (3726cdb)
  • template: run a template from the configured folder without a per-file choice (#1023) (#1343) (ce2b08d)
  • templates: support format syntax in the template path (#620) (#1337) (c2ee449)
  • templates: support multiple template folder paths (#1170) (#1325) (0da7ef6)
  • uri: support x-callback-url for the QuickAdd URI (#1070) (#1339) (f111d45)
  • user-scripts: store secret settings in SecretStorage (#1373) (288a1b5)
  • user-scripts: support stable secret option ids (0b26d76)
  • value: allow commas inside quoted multi-select options (#239) (#1345) (6e229b1)

Performance Improvements