Thank you for the support. Everything is working now as expected.
I am sharing the final result, because it may be useful for somebody else as well.
The below script is called by and Alfred workflow to search for URL’s in DEVONthink. It will search in a defined database and within that database in a defined group. Both values are configured in Alfred.
The workflow is activated by a hot key and when you start typing it will search in the bookmarks as found in DEVONthink and do a match on either the name, the URL or a tag.
I cannot upload the Alfred workflow here but if there is interest, I can make a couple of screenshots to get you going.
--
-- Created by: Fred Appelman
-- Created on: 12/02/2026
--
--
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
on run argv
if (count of argv) > 0 then
set searchKeyword to item 1 of argv
else
set searchKeyword to ""
end if
-- Get the name of the database and the name of the group from Alfred
set databaseName to (system attribute "database_name")
set groupName to (system attribute "group_name")
tell application id "DNtp"
-- Try to set the database
try
set db to database databaseName
on error errmsg
return my error_json("Error: No such database '" & databaseName & "'")
end try
-- Try to set the group
set theGroup to get record at groupName in db
if theGroup is missing value then
return my error_json("Error: No such group '" & groupName & "'")
end if
-- Retrieve all bookmarks from the specified group and database
set {recNames, recURLs, recTags} ¬
to {name without extension, URL, tags} ¬
of ((children of theGroup) ¬
whose (kind is "Web internet location"))
-- Filter them on the searchkeyword
set {filteredNames, filteredTags, filteredURLs} to my filterOnKeyword(recNames, recTags, recURLs, searchKeyword)
-- Convert to JSON
set objects to my convertToObjectList(filteredNames, filteredTags, filteredURLs)
return my to_json(objects)
end tell
end run
-- Convert the 3 separate lists to a combined array of objects
on convertToObjectList(filteredNames, filteredTags, filteredURLs)
set objects to {}
repeat with incr from 1 to filteredNames's length
set urlTitle to item incr of filteredNames
set urlAsText to item incr of filteredURLs
set theTags to item incr of filteredTags
copy {the_title:urlTitle, the_url:urlAsText, the_tags:theTags} to the end of objects
end repeat
return objects
end convertToObjectList
-- Filter the the given lists using the keyword into filtered lists
on filterOnKeyword(recNames, recTags, recURLs, searchKeyword)
if searchKeyword is "" then
-- If not searching, return the lists unchanged
return {recNames, recTags, recURLs}
end if
set filteredNames to {}
set filteredTags to {}
set filteredURLs to {}
-- Loop over all the lists. The lists have the same length
repeat with incr from 1 to recNames's length
set theTags to (item incr of recTags)
if (item incr of recNames) contains searchKeyword ¬
or (item incr of recURLs) contains searchKeyword ¬
or my hasMatchingTag(theTags, searchKeyword) then
copy (item incr of recNames) to end of filteredNames
copy (item incr of recTags) to end of filteredTags
copy (item incr of recURLs) to end of filteredURLs
end if
end repeat
return {filteredNames, filteredTags, filteredURLs}
end filterOnKeyword
-- Check if the tags match the search keyword
on hasMatchingTag(theTags, searchKeyword)
repeat with incr from 1 to theTags's length
set tag to (item incr of theTags)
if (tag contains searchKeyword) then
return true
end if
end repeat
return false
end hasMatchingTag
-- Logic to conver to JSON understood by JSON
on to_alfred_json(the_url)
set theTitle to (get the_title of the_url)
set theURL to (get the_url of the_url)
return "{
\"title\": \"" & theURL & "\",
\"subtitle\": \"" & theTitle & "\",
\"arg\": \"" & theURL & "\",
\"quicklookurl\": \"" & theURL & "\"
}"
end to_alfred_json
on empty_json()
return "{
\"title\": \"No such URL\"
}"
end empty_json
on error_json(message)
set saveTID to text item delimiters
set payload to "{
\"title\": \"" & message & "\"
}"
set json to "{\"items\": [" & payload & "]}"
set text item delimiters to saveTID
return json
end error_json
on convert_list(objects)
set json_payload to {}
repeat with the_url in objects
set converted to to_alfred_json(the_url)
copy converted to the end of json_payload
end repeat
return json_payload
end convert_list
on to_json(objects)
set saveTID to text item delimiters
set text item delimiters to ","
set json_payload to convert_list(objects)
if (count of json_payload) = 0 then
set json_payload to empty_json()
end if
set json to "{\"items\": [" & json_payload & "]}"
set text item delimiters to saveTID
return json
end to_json