Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

Inline Ask

Hølje BergeHølje Berge2 downloads

Ask an AI inline: wrap a question in ?, ?? or ??? and get answers that replace it in place. Uses your own OpenRouter key.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates2

Ask an AI a question right where you are writing in Obsidian. Wrap the question in question marks; the number of marks sets how hard the model works:

Syntax Level What happens
?question? easy A quick model shows a dropdown of short alternatives under the question.
??question?? medium Same dropdown from a stronger model; may take a few seconds.
???question??? hard Answered in the background; the question is replaced in place when done.

Example: type The answer is ?whats 2+2? and a dropdown shows 4 / 2 + 2 is 4 / it's 4. Pick one with the arrow keys and Enter, and the whole ?whats 2+2? is replaced. Esc dismisses it and leaves the text as it is; so does simply typing on.

With ???, the question is dimmed with a ⏳ while you keep writing, in this note or another one. When the answer arrives the plugin finds the exact ???question??? text again (it may have moved) and replaces it. If you edited or deleted the question in the meantime, the answer is discarded and a short notice tells you so. If the note is not open any more, the file is edited atomically with vault.process. Only the note the question is in is ever changed.

When it triggers

A request is sent only right after you type the closing marker, and only once per trigger. Moving the cursor, pasting text or reopening a note never sends anything. To avoid false triggers in normal writing:

  • the opening run must be at the start of a line or after a space or opening punctuation (( [ { " ' “ ‘ « * _ ~), and be followed directly by a character that is not a space or ?;
  • the closing run must directly follow a non-space character, and its length must equal the opening run's (1, 2 or 3; runs of 4 or more never trigger);
  • the question is 1-500 characters on one line;
  • nothing triggers inside fenced code blocks, inline code, frontmatter, $$ math blocks, inline $math$, link targets ([text](…), [[…]]), URLs (https://…?a=1, www.…) or %% comments %%;
  • \? is a literal question mark and is never part of a trigger.

So Really? Yes? and example.com/?a=1 are left alone.

Privacy: what is sent, and where

  • Requests go directly from your device to OpenRouter (https://openrouter.ai/api/v1/chat/completions) using Obsidian's requestUrl. There is no other server.
  • Each request contains only: the question, up to N words of the same note before and after it (setting "Context words", default 30 each side, 0 = question only), a short fixed system prompt, and the model settings. Frontmatter is never included. Nothing else from the vault is sent.
  • The model list for the settings picker is fetched from https://openrouter.ai/api/v1/models (public, no key).
  • "Test connection" calls https://openrouter.ai/api/v1/key and sends a one-word test prompt.
  • OpenRouter and the model provider you choose handle the request under their own policies.

API key: per device, never synced

Each device stores its own OpenRouter key in Obsidian's SecretStorage, which lives in the app's local storage on that device, outside the vault. It is never written to a note, to data.json or to the log. The settings tab only shows whether a key is set. (If SecretStorage is ever unavailable, the plugin falls back to its own data.json on that device.)

With Self-hosted LiveSync: the key is not in the vault, so it cannot sync. The plugin's settings (.obsidian/plugins/inline-ask/data.json, models and options only) sync only if you turn on LiveSync's hidden file / customization sync.

Settings

All settings appear in Obsidian's settings search.

  • Connection: OpenRouter API key (save / replace / clear), Test connection.
  • Per level (easy / medium / hard): enabled, model (searchable picker over OpenRouter's live model list, showing price and whether the model supports structured output and reasoning), reasoning effort (sent as OpenRouter reasoning: { effort }; None sends no reasoning settings).
  • Behaviour: number of alternatives (2-5), context words, timeout for ??? answers (default 5 minutes).

Defaults (picked from OpenRouter's model list in October 2026; change them any time):

Level Model Reasoning effort
easy anthropic/claude-haiku-5.5 none
medium anthropic/claude-sonnet-5.5 low
hard anthropic/claude-opus-5.5 high

Dropdown answers are requested as JSON ({"alternatives": [...]}): with a JSON schema when the model supports OpenRouter structured outputs, otherwise with JSON mode or plain text, parsed leniently. Errors (no key, bad key, no credits, network) show as one row in the dropdown, or as a notice for ???.

Install

Requires Obsidian 1.13.0 or newer. Works on desktop and mobile (no Node or Electron APIs).

Manual install: build (below), then copy main.js, manifest.json and styles.css into <vault>/.obsidian/plugins/inline-ask/, reload Obsidian, and enable Inline Ask under Settings → Community plugins. Then add your OpenRouter key under Settings → Inline Ask.

Development

npm install
npm run dev     # watch build to main.js
npm run build   # type-check + production build
npm test        # unit tests (trigger parser, context, reply parsing)
npm run lint

Source layout (src/):

File Purpose
trigger.ts Pure trigger parser and protected-region detection (unit-tested).
typed.ts CodeMirror field: "a ? was just typed here" (one request per trigger).
context.ts Words before/after the question (unit-tested).
prompts.ts System prompts per level.
openrouter.ts OpenRouter client (requestUrl), model list, key check.
parse.ts Parsing model replies, locating text (unit-tested).
ask.ts Trigger detection in the editor, building requests.
suggest.ts EditorSuggest dropdown for ? and ??.
background.ts ??? jobs: pending decoration, relocation, replacement.
secrets.ts Per-device key storage.
settings.ts Settings tab and model picker.

Develop against a separate test vault, not a synced one.

Notes

  • The dropdown's "Thinking…" row is replaced with the answers through EditorSuggest's internal showSuggestions, since the public API has no refresh. If a future Obsidian version removes it, the dropdown would stay on "Thinking…"; check this first after an Obsidian update.
  • requestUrl cannot be aborted, so timeouts stop waiting but do not cancel the request at OpenRouter.

License

0-BSD

HealthExcellent
ReviewSatisfactory
About
Ask AI questions inline by wrapping text in 1–3 question marks. Use ? for quick dropdown suggestions, ?? for a stronger model, and ??? to run in the background and replace the question with the answer when it arrives.
AIWritingAutomation
Details
Current version
1.0.1
Last updated
5 hours ago
Created
5 hours ago
Updates
2 releases
Downloads
2
Compatible with
Obsidian 1.13.0+
Platforms
Desktop, Mobile
License
0BSD
Report bugRequest featureReport plugin
Author
Hølje BergeHølje Bergehbergeio
GitHubhbergeio
  1. Community
  2. Plugins
  3. AI
  4. Inline Ask

Related plugins

ChatGPT MD

A seamless integration of ChatGPT, OpenRouter.ai and local LLMs via Ollama into your notes.

Text Generator

Generate text content using GPT-3 (OpenAI).

Smart Templates

AI powered templates for generating structured content. Works with Local Models, Anthropic Claude, Gemini, OpenAI & more.

Copilot

Run AI agents such as Claude Code, Codex, and OpenCode inside your vault. Turn your second brain into a smart assistant that gets knowledge work done.

Homepage

Open a note, base, or workspace on startup, or set it for quick access later.

Templater

Create and use dynamic templates.

BRAT

Easily install a beta version of a plugin for testing.

Claudian

Embeds Claude Code/Codex and other local Agents as AI collaborators in your vault.

Linter

Format and style your notes. Linter can be used to format YAML tags, aliases, arrays, and metadata; footnotes; headings; spacing; math blocks; regular Markdown contents like list, italics, and bold styles; and more with the use of custom rule options.

LanguageTool Integration

Advanced grammar and spell checking, powered by LanguageTool.