Way more than a simple Find & Replace: a versatile and powerful tool for search supporting regex and bulk operations (update content following a given pattern, append, prepend, change format, bulk page titles change...).
- Complete overhaul of the UI: unified draggable panel with tabs for almost all features
- Input (search or replace strings) history and favorites
- Bulk Format now includes cleaning options
- Apply bulk operations to search results: Pre/Append and Format tabs now let you choose the block source β multiselect, current page/view, or search results
- Filter, sort and select matching blocks of search results or before applying Replace all
- View search result as raw text or rendered blocks
- Commands in context menu of multiselection, page reference and page title
- Search in page with an instant highlighting
- Search in graph with plain text or block references extraction
- Find & Replace either local, in blocks selection, page, workspace, or global, in the whole graph, with complete support of regular expressions.
- Extract highlights or bold in selection or page, and other advanced extraction features.
- Block <=> Page conversion, replacing in bulk their references.
- Bulk formatting or cleaning of selected blocks (header, alignment, view, case, clean syntax, remove styles, handle aliases, remove blank blocks)
- Bulk append/prepend strings, ie. at the beginning or/and at the end of a set of selected blocks.
- π Bulk change of page names or simple pages search, supporting Regex.
- Full regular expressions support
See changelog here for an overview of updates and new features __
π‘ All the commands are available via the command palette (Cmd-Ctrl + P). Enter "Find & R..." and you will see all of them.
Press Ctrl + S to open a search box similar to the browsers' search box usually called with Ctrl+F: the search results are instantly highlighted in the current page and switching from one to the other automatically scrolls the display.
But this search box is specially designed for Roam Research since it detects the words hidden in the collapsed blocks and expands them automatically, by checking Auto-expand blocks option.
You can control the scope of the search, it ca be:
- extended to the whole workspace (including linked references and pages in the sidebar),
- or limited to a selection of blocks (by selecting them before opening the panel or, when opened, by selecting them and clicking on 'Blocks' scope)
- or only to page titles.
You can also specify a logic operator if you enter multiple words:
- by default (
full str.), the whole string is searched, - but you can search each word separated by a spaces with the
ORoperator (at least one word), - or the
ANDoperator (all words must be present in the block, in any order).AND+also includes first level children blocks.
You can have a quick overview of the search results (including hidden blocks) by clicking ποΈ and copied in the clipboard as plain text (block references are resolved) and filter/sort the results (see below).
You can copy the block references with '((π))' and paste them anywhere in your graph.
The search engine support regular expressions, so that any kind of pattern can be found. See below for more details and examples.
Set search scope to "Graph" (or run Find & Replace: Whole graph search in the command Palette (just enter 'wg')). Click on ποΈ to open a dialog displaying the matching blocks in plain text or rendered as editable Roam blocks.
When you click ποΈ, matching blocks are displayed in a dedicated results dialog with the following features:
- Two view modes: Text (raw content, instant) and Rendered (full Roam rendering with links, embeds, formatting). Rendered mode uses lazy loading to avoid freezing the UI on large result sets, and paginates to 100 blocks per page with prev/next navigation.
- Page path toggle (rendered mode): show or hide the breadcrumb path above each block β toggled instantly via CSS, no re-rendering needed.
- Sort: by page name (alphabetical), by match count per page (descending), or by last edit date (most recent first). The date sort shows a flat list independent of page grouping.
- Filter: a live filter input narrows the displayed results by page name or block content.
- Collapse/Expand: page groups can be collapsed individually or all at once with a single button (not available in date sort mode).
- Block selection: each block has a checkbox; a footer "Select all / Deselect all" checkbox controls all visible blocks at once.
- Open in sidebar: selected blocks can be opened all at once in the right sidebar with the footer button.
- Apply bulk operations: footer buttons "Pre/Append N" and "Format N" open the corresponding tab with only the checked blocks pre-loaded as the target.
- Copy to clipboard: the dialog's submit button copies all results as plain text (page names + resolved block content).
Replace a given string with another at once or step by step.
The range of application depends on two factors:
-
the range of selection: if you have selected a set of blocks (blue highlighted with mouse or Shift + Up or Down), only the selected blocks and their expanded children will be processed. If you are using the recent multiselect feature with checkboxes on the right (enabled with Ctrl + m), only checked blocks will be processed. Otherwise, the current page will be processed, including the linked references and the blocks or pages opened in the right sidebar if you click on 'workspace' option.
-
the 'Include collapsed blocks' option (in the setting panel): if it's enabled, expanded AND collapsed blocks will be processed when clicking on 'Replace all' button. Otherwise, only the visible blocks will be processed. If you check 'Auto-expand blocks' option in the dialog box, collapsed blocks containing a matching string will be expanded and can be processed even if the former option is disabled.
π‘ Find & Replace can be used to remove some content in bulk: enter the content to remove in the Find field, and let the Replace field blank.
It can also be used to replace different writings of a word in a given alias. Suppose that you have written 'word', 'Word', 'words' and 'Words' in your graph and that you want to replace the last three by an alias to [[word]], e.g. [Word]([[word]]). You have just to write this regex in the find field: /Words?|words/ and this in the replace field: [$RegEx]([[word]]).
With great caution
For more safety, the ποΈ feature allows you to have a quick overview of blocks that will be changed before doing it. The results dialog (described above in the Search in the whole graph section) is the same interactive component: you can filter, sort, switch between text and rendered view, select blocks, and open them in the sidebar before committing to any replacement.
After a Find & Replace operation, you can insert anywhere in your graph the list of changed blocks (as block references). It's also available in the 'Undo' popup after each operation: if you click on Display changed blocks in sidebar, the list of changed blocks will be inserted on the [[roam/depot/find & replace]] page, with date and timestamp.
In option, you can keep a copy of each changed block in its old state, and display a table that compares the blocks before and after the Find & Replace operation, to identify unintended changes and to have a backup of critical changes. Each old version is copied as a child block of the block reference of the new version - and is therefore easily accessible thought inline rerence counter.
Extract highlights in selection or page command in the command palette extract only the highlighted strings, and add an alias to the original block.
On the same principle, but for advanced users, it's possible to extract only strings matching the regular expression in the find field, accordingly to the pattern in the replace field.
If this option is enabled (in the setting panel), not the entire blocks but only the matching strings will be displayed in plain text with ποΈ or copied to the clipboard with '((π))'. The replace field plays the role of a template with placeholders ($RegEx for the matching strings, $1, $2 for capture groups).
Convert a given page in a block, and replace in bulk all its references in block references, or the opposite ! It's now as easy as a simple Find & Replace: enter the name of the page (or block reference), then enter a block reference where the page will be converted as the original block to witch all the references will linked (or a new page name).
Options:
- If you enter 'DNP' in the block reference field (or let it blank), the page will be converted in a new block created on the today's daily note page.
- If 'move source content' is checked, all the block in the page will be moved under the new block (or all the children of the block will be move in the new page).
- If you run the
Convert this block => [[page]]command from the contextual menu of a given block, the original block reference and the page name will be automatically completed. - If you have a block reference like
((9jO7A7MwG))or a page reference like[[page]]in the clipboard, and run one of the conversion command with the command palette, the corresponding fields will be auto-completed.
Since it's a quite dangerous operation, it will be safer to check the impacted blocks first, with the ποΈ button.
The Page => Block conversion command is also available in page and page reference context menu: the corresponding page title will instantly be copied in the page input.
Apply to a set of blocks. Use the source selector at the top of the tab to choose which blocks to operate on:
- Multiselect: blocks drag-selected (blue highlight) or checked with Ctrl+M in the editor
- Main view: all visible blocks on the current page or zoomed block (default)
- Search results: blocks matching the last search β or a specific subset chosen in the π results dialog
The panel is split into two rows:
- Heading level: H1, H2, H3 or Normal
- Alignment: left, center, right, justify
- View of children: bullets, numbered list, document
- Case: UPPER, lower, Capitalize block, Capitalize Each Word, Capitalize each sentence (excluding page references, tags, attributes and block references)
-
Syntax: remove specific Roam syntax from block content (keeping the inner text where applicable):
- Remove page refs β strips
[[β¦]]brackets and#tag/#[[tag]]prefixes, keeping the page name - Resolve block refs β replaces
((uid))with the actual content of the referenced block - Remove buttons β removes
{{β¦}}buttons individually (content between multiple buttons on the same line is preserved) - All at once β applies all four of the above in sequence
- Remove page refs β strips
-
Style: remove inline style markers, keeping the inner text:
**bold**,__italic__,^^highlight^^,~~strikethrough~~, or all at once
-
Alias: transform markdown alias syntax
[label](url):- Keep alias only β replaces
[label](url)with justlabel - Keep URL only β replaces
[label](url)with just the URL - Alias with * β replaces
urlwith[*](url) - Remove bare URLs β removes
https://β¦URLs that are not part of a markdown alias[label](url)
- Keep alias only β replaces
-
Remove blank blocks (checkbox): deletes blocks whose content is empty or whitespace-only, provided they have no children. Always applied last, so blocks emptied by the other cleaning operations are also caught.
This command is also available in the multiselect context menu.
Insert some string (e.g. a tag) in bulk, at the beginning (prepend) or the end (append) of a set of blocks. Use the source selector at the top of the tab to choose which blocks to operate on:
- Multiselect: blocks drag-selected (blue highlight) or checked with Ctrl+M in the editor
- Main view: all visible blocks on the current page or zoomed block (default)
- Search results: blocks matching the last search β or a specific subset chosen in the π results dialog
Only expanded blocks are processed. This command is also available in multiselect context menu.
Tip: run a search, open π, uncheck the blocks you want to skip, and click "Pre/Append N" in the footer to apply only to your selection.
Enter the pattern to change in multiple page names (it can be a simple string as Project) and the replacing string. Before any change in your graph, you will see the list of page names containing this pattern and have the possibility to select or unselect page names to update. You can easily copy this page list to the clipboard or display it in the right sidebar.
In the input field, you can enter a /regex/ to match more precisely some pattern (ex: /(Project)/A.*/`) (without escape character) will match 'Project' only if it has a namespace beginning by 'A'. 'Project' here is a capture group (by the use of parenthesis), so the replacing string will only replace this captured group. See next section for more detials on how Regex and placeholders for matching pattern or capture groups can be used.
All text inputs (find, replace, prepend, append) remember the last 10 strings you used. Click the history icon on the right side of any input to open a dropdown with your recent values β click any entry to instantly fill the input.
You can favorite any entry (β) to pin it permanently at the top of the list, immune to the 10-item rotation. Unfavoriting moves the entry back into the regular history. Individual entries can also be removed with β. History is stored persistently across sessions via the extension storage.
Regular Expressions (often abbreviated to regex) are a powerful system to express and match any form of character pattern you can imagine. The general idea is that a given regex allows to express several sequences of characters. For example, we have seen above that /Words?|words/ allows to identify 'Word', 'Words' and 'words', but not 'word' (that we don't want to change). So with a single expression in the search field, you can find and modify different words in your graph simultaneously.
The syntax of regular expressions is very strict. Understanding the science behind them is not indispensable (it is a pure mathematical formalism), but you should learn the syntax and experiment with it before using it in Find & Replace (you can ask an LLM via Live AI to generate a regex for you and explainit, or learn and test your formulas here or read Learn regular expressions in about 55 minutes), unless you restrict yourself to reproducing a few simple examples like the ones below. Be very cautious because their effects is not always easy to grasp and can have a dangerous impact on your data. Don't use regex if you don't know what you do.
The most accessible feature is using the variable $RegEx as a placeholder for formating the replacement of matching strings:
in Replace field, you can insert $RegEx in the replacing string. E.g., to bold all matching strings, enter: **$RegEx**
There is 4 possible formating of the main variable (pay attention to upper and lower case letters):
$RegExleaves the machting string in its initial case. (R and second E are upper case)$REGEXcapitalizes all letters.$regexset to lower case all letters.$Regexcapitalize first letter.
Search regex support currently 2 capture groups, that mean patterns between parentheses that can be reproduced in the replace string with the placeholders $1 and $2.
You can click on ? button in Find & Replace dialog box to see these examples:
Regex have to be written between /slashes/ with simple \ backslash before special character to escape. Flag for global search (/g) is always set by default, you doesn't need to mention it.
In Find field:
/words?/, matches all 'word' (singular) or 'words' (plural) occurences,/sk(y|ies)/, matches all 'sky' (singular) or 'skies' (plural) occurences,/cheese|cake/, matches all 'cheese' OR 'cake',/[A-Z]\w+/, matches all words beginning with a capital letter,/.*/matches all text,/\(\([^\)]{9}\)\)/matches all block references,/\[\[([^\[^\]]*)\]\]/matches all page references (not nested) and capture page name,/\[([^\]]*)\]\(\(\([^\)]{9}\)\)\)/matches[alias](((refs)))and capture alias.
In Replace field:
$RegExis the placeholder corresponding to the machting strings (pay attention to the case),$REGEXcapitalizes all letters of the mathcing strings,$regexset to lower case all letters,$Regexcapitalize first letter,[$RegEx]([[page]])make each machting string as an alias of [[page]],$1replace each matching string (e.g. page references) by the first capture group (e.g. the page name),**$1** nΒ°$2insert two capture groups in a new formated string (only 2 capture groups are supported)
-
limits of live highlight on page feature: Text in code blocks are not highlighted. Likewise, if your search for strings including markdown syntax, or if the matching string is hidden by some markdown syntax (like the link in an alias), it will not be highlighted. A counter indicate how many strings can't be highlighted. You can see them with in plain text with the
ποΈbutton. But in any case, the words will be correctly detected and replaced. -
limits around the logic operators: The count of matching elements is not fully reliable with AND or AND+ operators. AND+ is not yet applied to the whole graph search, the algorithm must be optimized to give a result in a reasonable time.
If you want to encourage me to develop further and enhance Find & Replace extension, you can buy me a coffee β here or sponsor me on Github. Thanks in advance for your support! π
For any question or suggestion, DM me on X/Twitter and follow me to be informed of updates and new extensions : @fbgallet, or on Bluesky: @fbgallet.bsky.social
Please report any issue here.

