Protocol
Bob Mac Capture owns presentation, process orchestration, and settings. Capture grammar, completion data, previews, and vault mutation belong to bob (thin client decision). New capture behavior lands in bob and Capture syntax first; the app then decodes and presents it.
Capabilities are detected per response, never pinned to release numbers: unknown span kinds decode as neutral text, unknown contexts as generic rows, and absent additive fields decode to the behavior in the compatibility table. Upgrade bob when a row says so; nothing below invents a minimum release.
Capability requirements¶
bob must support these contracts before the panel can use them:
- A
bobbuild that supports@@route/@@route+block-idglobal destination declarations anywhere in the draft,capture-rewrite(includingswitch_block_id_separatorandstart_template),capture-complete --all-tasks,capture-task-id,capture-pomodoro-name, thetask_linkcompletion context for:picker queries (withnote_kind,block_id_suggestions,group,scheduled, andpulls_forwardcandidate fields), thetask_gotocompletion context for a whole-draft/query (note_pathand absolutetargetcandidate fields), thetask_parentcompletion context for leading and prose-terminal+(with the additivepickerdescriptor:kind: parent_task,scope: note|vault,scope_token,note_target,marker_range,trigger_removal_range, optionalaction_continuation_keys, and top-levelquery), the same descriptor on scoped@route+taskresponses,parent_replacementoncapture-task-idfor vault-wide ID-less picks,task_sectioncompletion for@route+block-id#,pomodoro_namecompletion for@route:block-id#and bare task-toggle@route+block-id#, thetask_block_idcompletion context for the@route^block-idordinary task-with-ID marker, the additive top-levelblock_idobject on both block-ID contexts (intent, marker range, body, allowed-character rule, used IDs, suggestions), the additivecreates_pomodorocreate-future-Pomodoro action,task_togglecapture JSON, the additivedropped_dependenciesrows andlink_guardobject (reasons,promoted,detail,drop_refused) on link, toggle, Ensure Next, and link-then-close captures, thetask_toggle_*parse spans, and the current task-toggle spellings: plain@route+block-idfor Ensure Next relocation to the implicit current/next Pomodoro,@route+block-id#pomodorofor named Ensure Next relocation or named-future creation, and suffixed@route+block-id!for the explicit two-way toggle (toggle_behaviorandtask_toggle_explicit_toggle), plus the atomic-start@route:block-id=<X>and@route:block-id#name=<X>suffix (pomodoro_startparse/capture JSON and thepomodoro_startspan, where<X>mirrors these<X>snippet: empty is 25 minutes,-offsets one 5-minute unit), plus whole-item+[N]/-[N]duration adjustments (pomodoro_adjustparse/capture JSON and thepomodoro_adjustspan, where each unit is 5 minutes and subtraction clamps at zero), plus whole-item++[N]/--[N]session shifts (pomodoro_shiftparse/capture JSON and thepomodoro_shiftspan, where each unit is 5 minutes and the count defaults to 1, so+,-,++, and--all work), plus whole-item=/=<X>session starts (pomodoro_startparse/capture JSON and thepomodoro_startspan, where<X>mirrors these<X>snippet and the capture summary carries the session's queued Task Links), plus whole-item=<X>#namenamed starts (thepomodoro_namespan over the name bytes, thepomodoro_start_namecompletion context with the additivenext_uprow marker, the=#incomplete state with itsinteractive_placeholderspan,x#nameclose near-miss diagnostics, and the additivecreated_pomodorocapture summary for new and "again" sessions), plus Pomodoro closexand its additivepomodoro_closecapture summary, plus the project-note@route^block-id+#pomodoromarker (the retired@route:block-id+spelling is a parse diagnostic), the trailing:id/^idproject-task tokens (project_task_block_idcompletion context with intentnew,project_task_link_marker/project_task_block_idparse spans, and the additiveproject_note.task_linkscapture object). Bulk templates require Bob's additivetemplate/template_rowparse and capture objects, field-indexedtemplate_placeholderandtemplate_fieldspans, thetemplate_rowincomplete need, and thetemplateroute-completion candidate. Go To and Control-\ today-Pomodoro landing and Bob Refs Control-Return also require bob-plugins bob-navigation-hotkeys ≥ 2.32.0 (or the version that shippedobsidian://bob-goto-task). Control-Return landing viaobsidian://bob-open-notesneeds bob-navigation-hotkeys ≥ 2.44.1, deployed to the vault withbob plugins sync. Older builds can still capture ordinary drafts, but global declarations, bare-@@absorption, the Add block ID flow, the Name Pomodoro flow, the task-section popup, and the task-toggle footer/preview report the local Bob error or an empty list until Bob is upgraded. An older Bob that returns scoped@route+taskcompletion without the additivepickerdescriptor keeps the inline parent-task list; vault-wide+andparent_replacementneed a Bob that emits the phase-one contract. An older Bob that sees bare@route+block-idas a missing-text sub-bullet reportstask text is required, which the panel surfaces unchanged. An older Bob that does not emitcreates_pomodorostill captures@route:id#namecreate-on-submit; the Mac app decodes a missing flag as false and simply omits the explicit Create row. An older Bob that omitspomodoro_startstill previews and captures@route:block-idwithout a session; the Mac app decodes a missing start object as no session and shows no timer row, while a malformed=<X>suffix surfaces Bob'sinvalid_pomodoro_startdiagnostic unchanged. An older Bob that omitspomodoro_adjuststill parses+5as an ordinary task; the Mac app decodes a missing adjustment object as no adjustment and shows no adjustment row, while an invalid magnitude surfaces Bob'sinvalid_pomodoro_adjustmentdiagnostic unchanged. An older Bob that omitspomodoro_shiftstill parses++3as an ordinary task; the Mac app decodes a missing shift object as no shift and shows no shift row, while an invalid magnitude surfaces Bob'sinvalid_pomodoro_shiftdiagnostic unchanged. An older Bob that reports=as incomplete and=3as a task shows no start card or Start footer for whole-item starts; the panel simply previews that older behavior, so upgrade Bob before using=/=<X>. A start summary whosetasksarray is absent still previews: the card shows the session with no queued rows. An older Bob that omitspomodoro_closehas no close preview or Close footer; upgrade Bob before usingx. A close summary whose task, carried, notes, or next fields are absent still previews: booleans read as false, arrays as empty, and missing lines as zero, and unknown task roles degrade to a neutral row. A close summary whosein_progress,park,complete,drop,task_links, orindexfields are absent still previews as today's unnumbered card: the spec decodes as no selection, rows decode as unnumbered, and no hint, summary, or badge renders. Whole-itemx(including thex*andx!selection forms) reportspomodoro_closemode with apomodoro_closespan and a{"raw": "x"}parse spec (rawpreserves the exact token,x*parks all numbered links andx!completes them); link items keeppomodoro_link/pomodoro_taskmode with apomodoro_closespan kind over the suffix. A selection-bearing close addspomodoro_close_in_progress,pomodoro_close_park,pomodoro_close_complete, andpomodoro_close_dropspans, anin_progress/park/complete/dropparse spec plus additivepark_all/complete_allintent flags, andtask_linksplus per-rowindexin the capture summary; a dangling,/~reports modeincompletewith apomodoro_close_taskneed and aninteractive_placeholderspan instead of an error. A present-but-empty*/!group selects all numbered links left after explicit assignments; explicit forms such asx*1andx!1narrow the action to task 1. Two empty wildcard groups compete and need numbers on at least one group. One entry may sit on the close line itself (x wired the lexerlogs to task 1 for a plain close, or to the first eligible top-level worked link with wildcard intent;x1,3 3 fixed the flakelogs to task 3): an explicit number adds apomodoro_close_log_indexspan in cyan on the close line while the default adds none, and a dangling inline number (x 2) reports modeincompletewith apomodoro_close_log_textneed and aninteractive_placeholderspan over the number. Several entries use ⌃J bullets (xplus- 1 wired the lexer, with- …detail bullets under entries), which add alogparse spec with the typed entries in order, each carrying itsdetails. Bullets may omit the number: unnumbered bullets log in order to the close's worked tasks (x3,4plus- foo barplus- baz bamwrites exactly what- 3 foo barplus- 4 baz bamwrites), and a single worked task takes them all. Bullets are numbered all or none, and a leading number is always a task number (to log text that starts with a number, number every bullet). Numbered entries addpomodoro_close_log_indexspans in cyan over each entry index while positional entries get no index chip;capture-parseomitslog[].indexfor entriesbob captureresolves against the running session, and the app decodes a missing index as nil. Entry and detail text keeps wikilink spans but is otherwise neutral prose, and a dangling bullet (xplus- 1) reports modeincompletewith apomodoro_close_log_textneed and aninteractive_placeholderspan over the number instead of an error. Inline entries require a bob that understands them; an older bob reportsinvalid_pomodoro_closeon the entry. An older Bob that omitslogdecodes as no typed entries, an older Bob that omitsdetailsdecodes each entry without details, and an older Bob that omitstyped_work_logortyped_work_log_detailsdecodes as empty so the card shows only the cappedwork_logpreviews. A parked (*<P>) close records normal In Progress work without carrying those links forward; parked rows keep readable, unstruck, undimmed text with their actual transition, apause.circleaccent besideParked \u00b7 not carried, and VoiceOver reading the task number, text, actual status, and "parked, not carried to the next Pomodoro". The summary usesContinue,Parked,Complete,Deferred, andDroppedgroups in that order (for exampleContinue 1 \u00b7 Parked 2, 3 \u00b7 Complete 4, 5);Continuemeans ordinary worked links carried onward and never names a task status.x0*2reportsContinue none \u00b7 Parked 2. A dropped (~<K>) close removes those links from today without carrying or starting them; the card strikes and dims dropped rows, summarizesDropped 4, 5, and reads "drops from today" for VoiceOver. A dropped row adds a "stays" caption naming the lane the task keeps. The x*/x!all-task selection behavior requires the corresponding updated Bob executable. With an older Bob, the app displays that Bob's actual preview and submits the untouched draft through one Bob capture call; it never parses selection lists in Swift or simulates the new behavior. The app keeps schema-version rejection unchanged. A whole-item=/=<X>start reports the same numbered lineup: per-rowindexin the capture summary, adroplist on the parse spec and capture summary, and removed rows indroppedwith theirindex, pre-imageledger_line, andnested_linescount; a trailing~<K>adds apomodoro_start_dropspan in the same muted gray aspomodoro_close_drop, and a dangling~/,reports modeincompletewith apomodoro_start_taskneed and aninteractive_placeholderspan instead of an error. A start summary whosedrop,dropped,index, ornested_linesfields are absent still previews as today's unnumbered card: the spec decodes as no drop, rows decode as unnumbered without badges, and no drop hint or summary renders.toggle_directionislinkorunlinkwithstatus_changedon every result: linking shows the added link withset Next,stays Next, orstays In Progress, and unlinking shows the removed-link count withstays <status>. Older Bob builds that sendnext/openstill decode to the same Set Next/Open footers. The app labels actions and notifications from Bob's returned behavior metadata, so a response that omitstoggle_behaviorstill shows the two-way Set Next/Open footer, never Ensure Next. Captures that change today's## Pomodorossection also report a top-levelplan_budgetobject with before/after theme and link meters, anadded_themeslist, and cap warnings that fire only while the batch grows a meter past its cap; the same destination carries aroleofcurrent,next_up,named, orcreated. Withplan.strict: truea batch that creates a new named Pomodoro past the theme cap is refused atomically (exit 1, JSONcode: plan_theme_cap_exceeded), andpomodoro_namecreate rows preview the resulting theme count withplan_themes_afterandplan_themes_cap.plan_budgetalso carriesadded_theme_refs, the hue refs for the added names: the+1 BOBdelta chip wears the first added hue and created destination, start, toggle, and project-note rows wear theme pills.pomodoro_nameandtask_toggle_pomodoro_namespans carry per-componentthemesrefs, so the editor tints known names behind the unchanged syntax color; unknown and exempt names stay neutral. Agenda entries carrythemesrefs, so group headers wear pills and the one-row fold wears swatches; home dots are untouched. Refs Today rows carrythemesrefs for the same pills. The shared catalog, hue, and menu rules are defined in the Pomodoro themes contract. An older Bob that omitsplan_budget,role,plan_themes_after/plan_themes_cap,added_theme_refs, span or entrythemes, orcodestill previews and captures; the Mac app decodes each as absent and renders the destination row as→ NAME, omitting only the meter capsules, the cap badge, the strict hint, and the theme tints. Agenda and Refs rows from an older Bob render the plain name with no pills. A trailing#nowtag is the ordinary trailing-tag error like any other#tag, and#nowtyped before the route is plain body text. The^active-task picker lists In Progress and Next tasks only. An older Bob that still sends thenowflag, thenow_tagspan or completion context, or thenowpicker group still previews and captures; the Mac app decodes an unknown span as neutral, an unknown context as a generic row, and an unknown group asnote. Saving links to the reading queue needs a Bob that emits therefcapture kind with the additiverefobject,refparse mode, and theref_urlspan. An older Bob keeps capturing a bare link as an ordinary inbox task; the Mac app decodes the missingrefobject as no reference preview and keeps the standard card, so upgrade Bob before queueing links. Filing a link needs a Bob that resolves the canonical parent: the additiveref.parentobject (route,label,kind,source,alias) on capture results,ref_parent(token,source) oncapture-parserefitems, andproject_name_aliasesoncapture-targetsentries. A bare URL that will queue under the default parent opens the route list on its own with the header File under: cached inbox, area, and project targets with the last-used parent first, thenmac_inbox; typing filters with aliases included (bob · aka bob-cli). Accepting inserts@<route>at the end of the draft; Esc keeps the default (→ mac_inbox · file it later) and the list does not reopen until the URL changes. Library hits (in_library,in_intake,clipping,duplicate) never open it. The queued preview reads📖 Queue · example.com/essay → sase(plus the parent's kind for an explicit@route), and the confirmation and notification readQueued for reading → sase. The last-used parent is remembered after a successful submit. Route completion everywhere ranks alias matches after prefix route matches. An older Bob that omitsref.parent,ref_parent, orproject_name_aliasesstill previews and captures; the Mac app decodes each as absent, keeps today's wording, never auto-opens File under, and matches routes without aliases, so upgrade Bob before filing links. Inbox routing needs a Bob that reports the additiveinbox_routeobject (supported, candidates, and destinations) on every capture JSON and accepts repeated--inbox-route KEY=<relative_path>(orKEY=to keep) answers plus the hidden--require-inbox-route-choiceguard; without it the app captures without asking.
The app never invokes a login shell to find bob. A Settings override must be an
absolute executable path.
The executable search paths and the Settings override live in Install.
Timeouts and guards¶
Every bob invocation is bounded by a 20-second timeout (BobProcessClient.defaultTimeout)
that terminates and reaps a wedged process instead of leaving the panel waiting
indefinitely; a fired timeout surfaces as an actionable BobClientError.timedOut. Quit
cancels every outstanding invocation via cancelActiveProcess().
If Bob rejects the exact --refuse-override flag as an
unexpected argument (exit 2), the app retries without that guard and remembers the
answer for that executable. --require-pull-in-choice is never retried: it goes out
only after a preview from the same executable advertised pull_in.supported, so an
older Bob never sees it; it also shows a note that this Bob lacks successor-choice
checks. --require-inbox-route-choice goes out under the same positive gate (a
preview, or any decoded capture JSON, that carried inbox_route.supported == true,
remembered per executable identity), and an older Bob that still receives it retries
without the flag the same way. Other failures and explicit stale-key refusals are never
retried. The app only sends explicit offer keys from a matching preview or write-free
refusal back to bob capture. An older bob never overrides on =, so retrying without
--refuse-override is safe.
If Bob rejects -a / --attended on ref scan as an unexpected argument (exit 2),
the app retries without that flag and remembers the answer for that executable, the
same way it remembers the capture guard flags.
Template saves send --template-origin only after a successful template-list request from that same executable; see Saved templates.
Required commands¶
These must exist; without them the feature they serve stays hidden or refuses with bob's own error:
capture-parse --format json(spans, needs, replacements, ranges,cursor_after)capture-complete --all-tasks --cursor BYTE --format json(candidates, replacements)capture-rewrite --cursor BYTE --format json(marker absorption, separator toggles, relation-label attachment, template start)capture --dry-run --no-clip --format json(live preview) andcapture --format json(submit)capture-pomodoros --format json --tasks(agenda, counts, landing); plaincapture-pomodorosonly feeds the close-comma count on older buildscapture-task-id/capture-pomodoro-name(Add block ID / Name Pomodoro prompts)capture-targets(route list),capture-templates list/save(template shelf)ref list -R all -A -f json(Refs snapshot, schema 1; add-gwhile any row still lacks anaddeddate or git instant)plan -f json(Refs Today join, schema 2)ref scan -a -w -f json(Refs scan report, schema 1;-ais omitted after an older bob rejects it)ref show <note-path> -f json(inspector hydration)ref rename(Rename card)vault-sync -q(Refs pull on panel show and before ⌘R)
Bob Refs ⌘S and the enabled Highlights-save trigger use this scan command.
Every writing bob ref scan that acquired the scan writer lock writes that JSON
envelope to <state>/bob-cli/ref/last-scan.json (XDG_STATE_HOME, else
~/.local/state) and, on macOS, posts the Darwin notification
org.bobs.bob.ref.scan-finished. Bob Refs observes that name with
notify_register_dispatch, reads the receipt off the main thread (bounded at 4 MB),
and ignores a duplicate content hash. Launch never reads a receipt.
Optional commands¶
These features stay hidden when the installed bob does not provide the command:
capture-related --format json -- DRAFT(settled similar-task matches and draft anchors, schema 1)
Optional fields¶
Absent fields decode tolerantly and only hide their own row, badge, or offer:
creates_pomodoro,pomodoro_start,pomodoro_adjust,pomodoro_shift,pomodoro_close(pluslog,details,typed_work_log,typed_work_log_details)pomodoro_start.override,toggle_behavior,toggle_directionwithstatus_changedplan_budget, destinationrole,plan_themes_after,plan_themes_cap,code,added_theme_refs- span
themes(pomodoro_name,task_toggle_pomodoro_name), agenda entrythemes, Refs Today rowthemes refwithref.parent,ref_parent,project_name_aliases- Refs list fields
blocked,task,added_at; snapshot cache keygit_added_at; copy-cardmarker_id - Scan report fields
generated_at,summary.held,held[],notes[].marker_write(mode,editor_saved_first,status.from/to) block_idobject,pickerdescriptor,parent_replacement,pomodoro_start_namecontextopen_notes,homes,task_links, successor-offer payloadsinbox_route(candidates, destinations,repaired_files,renamed_block_ids,needs_reconcile) andrefuseddetail oninbox_route_refusedrelation_grammar, relation-labelrelationtoken metadata andowner,relation_updates,linked_from_line_updates,minted_relation_block_ids,mirror_skipped, relation-labelcount/typed- relation vocabulary: label
key/inverse/hide_replacement/existing/hidden,hidden_count,one_off,bob relations list/hide/unhide,relation_label_hides[], structured capture warnings - Retired inputs (
nowflag,now_tagspan,nowpicker group) decode as neutral: unknown spans as neutral text, unknown contexts as generic rows, unknown groups asnote
Compatibility¶
| Feature or field | Expectation | When absent | Reader action |
|---|---|---|---|
@@route / @@route+block-id declarations |
Unmarked items route to the declaration | Ordinary draft capture; bare markers report the local bob error or an empty list |
Upgrade bob for declarations |
capture-rewrite, switch_block_id_separator, attach_relation_label, start_template |
@@ absorbs markers; ^ / : toggle the separator; | attaches to an eligible relation token; @@@ starts a template |
With an older bob, the third @ types literally; a space before | stays literal and only ~note:id| opens the relation card; other rewrites follow that bob's behavior |
Upgrade bob for relation-label attachment and template start |
capture-complete --all-tasks |
Full candidate lists | Empty list or local bob error |
Upgrade bob |
task_link / task_goto / task_parent / task_block_id contexts |
Picker rows with replacements and intents | No rows; calm browse hint instead of a dry-run error | Upgrade bob |
picker descriptor, parent_replacement |
Vault-wide + picks, ID-less splice |
Inline list only; prompt asks to update bob |
Upgrade bob |
pomodoro_name, task_section completion |
# completion after resolved markers |
No rows until bob is upgraded |
Upgrade bob |
creates_pomodoro |
Explicit Create row | Captures without the explicit row (decoded false) | Upgrade bob to see it |
pomodoro_start / pomodoro_adjust / pomodoro_shift |
Session, adjust, and shift rows | Omitted rows; malformed suffixes surface bob's diagnostic |
Upgrade bob for = / +N / ++N |
pomodoro_close with log entries |
Close card with typed Work Log | Standard card; no close preview | Upgrade bob before x |
toggle_behavior |
Ensure Next vs Set Next / Open labels | Two-way labels; status and relocation still exact | Upgrade bob for exact labels |
plan_budget, role, theme caps |
Meter capsules, badges, strict hint | Destination row only (-> NAME) |
Upgrade bob for meters |
added_theme_refs, span/entry/row themes |
Pill and swatch tints in the editor, agenda, previews, and Refs Today | Plain names; neutral pills only where a budget exists | Upgrade bob for theme tints |
ref object |
Queue preview card, footer action | Ordinary inbox task | Upgrade bob; -R disables queueing |
ref.parent, aliases |
File-under prompt, alias-ranked routes | No auto-open; prefix matching only | Upgrade bob for filing |
ref list schema 1, optional -g |
Refs snapshot with git instants | Refresh fails on any other schema; -g omitted until a row still lacks added/added_at |
Upgrade bob for Refs |
blocked on a Refs row |
Blocked rows sort last in Next/Ready | Decoded as not blocked | Upgrade bob for blocked ranking |
task on a Refs row |
Today joins on (path, block_id); ⌃↵ opens the reading task |
Note-path join; two tasks on one parent can both light up; ⌃↵ beeps | Upgrade bob for task join |
added_at |
Timed Newest groups and captions | Nil; day-only or undated ranking | Upgrade bob for instants |
plan -f json schema 2 |
Today pills from the ledger | Last good Today; footer can say Update failed | Upgrade bob for Today |
ref scan -w -f json schema 1 |
Scan report, Just scanned, notifications | Banner or "This bob can't report scans yet" | Upgrade bob; retry ⌘S |
ref scan -a / --attended |
Attended scan: never hold marker writes because Highlights is in use | Retry without -a and remember for that executable |
Upgrade bob for attended scans |
Scan generated_at, summary.held, held[], notes[].marker_write |
Open-PDF footer clauses, busy banner, grouped notifications | Decoded empty; scan still lists created notes | Upgrade bob for coordinated PDF writes |
ref show |
Hydrated inspector notes, tasks, outline | Basic inspector plus dim "Notes unavailable" | Upgrade bob for notes |
ref rename |
Rename card writes through bob |
Card stays open with bob's refusal |
Upgrade bob for rename |
vault-sync -q |
Background Refs pull | Pull failure is logged only; list stays | Upgrade bob for pull |
marker_id |
Copy-card I row |
I asks for a newer bob; other copy rows still work |
Upgrade bob for marker IDs |
open_notes |
Control-Return lands on captured lines | Tabs open without landing | Upgrade bob; needs plugin 2.44.1+ |
--tasks on capture-pomodoros |
Agenda, counts, =#name names |
Agenda hidden; counts from plain output | Upgrade bob, then Recheck |
pomodoro_start_name |
Start list for =#name |
No rows | Upgrade bob |
Template spans, @@template: |
Template rows, shelf, preview capsule | Ordinary drafts keep working; refuse before writing | Upgrade bob for templates |
override, guard flags |
Orange banner; guarded commit; choice card | Plain start; retry without the flag is remembered | Upgrade bob for overrides |
pomodoro_blocks, task_blocks |
Full block views below the stack | Standard item stack | Upgrade bob for blocks |
| Successor offers | Grouped Pull-In choice card | Single legacy wording | Upgrade bob for offers |
| Inbox routing | Route card before submit | Captures without asking | Upgrade bob |
sub_bullet_depths, global_destination, items |
Exact children; one shared-scope line | Depth 1; per-item targets | Upgrade bob for shared scope |
homes |
Derived names and home chips | Previous naming | Upgrade bob for names |
| Close-comma assist field | Auto-inserted , |
Assist off; digits type normally | Upgrade bob for assists |
relation_to / relation_from completion |
~ / ~~ picker rows with replacements and intents |
No rows; calm browse hint instead of a dry-run error | Upgrade bob for relations |
relation_label completion and relation metadata |
Relation card suggestions with counts, typed row, token range, direction, and owner | Without the metadata, the app uses its legacy token scan; without the completion context, no card opens | Upgrade bob for relation labels and exact token ranges |
relation_label key / inverse / hide_replacement / existing / hidden, hidden_count, one_off |
Canonical keys, inverse phrases, || insertions, typed validation flags, Hidden pill, one-off mode |
Local label folding, no inverses, | insertions only, no Hidden section or pill, no one-off mode |
Upgrade bob for the relation vocabulary |
bob relations list -f json, hide, unhide on the relation-label-pref lane |
Hidden section, ghost hide/unhide rows with ⌃D undo | No Hidden pill; Ctrl-D and Ctrl-H give the update hint | Upgrade bob to hide relation labels |
relation_label_hides[], structured hides_existing_relation_label warning |
Amber preview row, card warning, · hid notification suffix |
No hide rows; structured warnings decode as text | Upgrade bob for one-off hides |
relation_grammar |
~ parses with relation spans; capability warning stays hidden |
Calm predates ~ links warning; first ⌘↩ only shows it |
Upgrade bob for ~ |
relation_updates[], linked_from_line_updates[], minted_relation_block_ids[], mirror_skipped[] |
🪢 preview rows, managed-line suppression, separate notification counts | Legacy preview without relation rows; notifications omit relations | Upgrade bob for relation previews |
capture-related |
A settled Similar tasks band beneath matching task cards | Band stays hidden; ordinary preview and capture continue | Upgrade bob to show similar tasks |
The app waits 350 ms after an edit before requesting capture-related. An older bob
that rejects the command is remembered for that executable identity, so the app keeps
the band hidden without retrying on later drafts. Changing the executable identity
rechecks support.