Inline Commands Directions¶
How to add a new inline command — decorator, context scope, consume mode, persistence
When to use¶
user wants to add a new right-click menu item or #wb/cmd/* tag command
Directions¶
Adding an inline command¶
1. Write the handler¶
Drop a new file in work_buddy/inline/handlers/:
from work_buddy.inline.registry import inline_command
from work_buddy.inline.models import InlineContext
@inline_command(
name="mything/new",
surfaces=["menu", "tag"],
consume_mode="annotate", # strip | annotate | replace | leave
persistent=False, # True → registers a PersistentWatcher instead of running
menu_label="Do my thing", # shown in right-click menu (prefixed with 'Work Buddy: ')
interactive=True, # route through thread chat
context_scope="paragraph", # line | paragraph | section | file
description="One-sentence description for the menu.",
)
async def mything_new(ctx: InlineContext) -> dict:
# ctx.surface, ctx.file_path, ctx.selection, ctx.line_text, ctx.paragraph, ...
text = ctx.text_for_llm()
# ... do the work ...
return {"ok": True, "thread_id": ...}
Import the module in work_buddy/inline/handlers/__init__.py so registry auto-load picks it up.
2. Choose consume mode¶
| Mode | Effect | Use when |
|---|---|---|
strip |
Remove the tag from the note | Tag was a single-use trigger and you don't want an audit trail |
annotate |
Leave tag; append a > [!work-buddy] callout below |
Default for most one-shot commands |
replace |
Rewrite #wb/cmd/foo → #wb/cmd/foo/done |
Breadcrumb without callout clutter |
leave |
No-op | Persistent watchers (the tag IS the watcher) |
3. Persistence¶
Set persistent=True to register a PersistentWatcher on first tag detection instead of running immediately. The inline-sync sidecar job wakes watchers on their schedule and cancels them when the tag is removed from the vault.
4. Context scope¶
| Scope | Text passed in |
|---|---|
line |
Just the cursor/tag line |
paragraph |
Blank-line-separated block |
section |
Enclosing markdown heading section |
file |
Full note |
All scopes are pre-populated in InlineContext; the handler can use whichever fits.
5. Tag syntax¶
Single namespace: #wb/cmd/<handler-name>. Example: #wb/cmd/task/new. The handler's declared persistent field decides whether the tag is consumed or registered.
Reuse¶
- Thread chat for interactive confirmation:
thread_create,thread_ask,thread_poll - Tag reads:
work_buddy.obsidian.tags.get_file_tags(path)(returns positions) - Note I/O:
work_buddy.obsidian.bridge.read_file/write_file - Consent:
work_buddy.consentfor destructive mutations