URL.Bookmark Class (bookmarks)
An instance of the URL.Bookmark class records the permission to access a given URL and will restore that permission, as well as a possibly renamed file, at a later point.
Because of security features in iOS/iPadOS/macOS the user must actively approve the use of files and folders located outside of the current application’s sandbox security zone.
To eliminate the need for the plug-in user to locate and select a specified location or file used by the plug-in, every time the plug-in is run, you can store an approved reference to the user-selected location in the system Keychain. This reference is called a “bookmark.” Stored bookmarks can be retrieved and used without further user interaction.
The storing of bookmarks in the system Keychain is accomplished through the use of the Credentials class.
Credentials Instance Functions
readBookmark(service: String) → (URL.Bookmark or null) • Reads the entry for the given service identifier and attempts to return it as a URL.Bookmark, or null if no such entry exists.
writeBookmark(service: String, bookmark: URL.Bookmark) → ( ) • Stores the URL.Bookmark persistently for later access.
On macOS, bookmarks can be located in the Keychain Access application by filtering using the credential service title:
(⬇ see below ) The bookmark credential in the Keychain Access application (macOS):

(⬇ see below ) Info for the bookmark. NOTE: the value of the password is the bookmark:

URL.Bookmark Class Functions
fromURL(url: URL) → (URL.Bookmark) • Creates a URL.Bookmark from an existing URL, which should have been returned by FilePicker. This can then be stored in a Credentials object to persistently record the permission to access this URL. (see plug-in example in this section)
URL.Bookmark Instance Functions
access() → (Promise of URL.Access) • Attempts to resolve the instance into a URL and grant access to it through the returned Promise. Access to the URL will only last as long as the URL.Access object exists (which should not be stored longer than necessary).
URL.Access Class
An instance of the URL.Access class holds the temporary access given by the URL.Bookmark.access() function. These should not be stored longer than needed.
url (URL r/o) • The URL being accessed.
Example Plug-In
Here is an example plug-in (compatible with all Omni apps) that demonstrates how to store and retrieve instances of the URL.Bookmark class:
(⬇ see below ) To remove the stored bookmark, hold down the Control key when selecting the plug-in from the Automation menu:

Bookmark Example: Open Chosen/Stored Directory
/*{
"type": "action",
"targets": ["omnigraffle","omnifocus","omniplan","omnioutliner"],
"author": "Otto Automator",
"identifier": "com.omni-automation.all.bookmark-example",
"version": "1.2",
"description": "This plug-in uses the URL.Bookmark class to create and retrieve stored bookmark.",
"label": "Bookmark Example",
"shortLabel": "Bookmark Example",
"paletteLabel": "Bookmark",
"image": "bookmark.square"
}*/
(() => {
credentials = new Credentials()
serviceTitle = "source-folder"
const action = new PlugIn.Action(async function(selection, sender){
try {
// TO REMOVE BOOKMARK HOLD DOWN CONTROL KEY WHEN SELECTING PLUG-IN
if (app.controlKeyDown){
alertMessage = "Remove the stored bookmark?"
alert = new Alert("Confirmation Required", alertMessage)
alert.addOption("Remove")
alert.addOption("Cancel")
alert.show(buttonIndex => {
if (buttonIndex === 0){credentials.remove(serviceTitle)}
})
console.log("Bookmark Removed")
return "Bookmark Removed"
} else {
// RETRIEVE BOOKMARK
bookmark = credentials.readBookmark(serviceTitle)
// IF NO BOOKMARK, ASK FOR FOLDER
if(!bookmark){
picker = new FilePicker()
picker.folders = true
picker.multiple = false
picker.message = "Select folder to be bookmarked:"
chosenDirectoryURLs = await picker.show()
bookmark = URL.Bookmark.fromURL(chosenDirectoryURLs[0])
credentials.writeBookmark(serviceTitle, bookmark)
bookmark = credentials.readBookmark(serviceTitle)
}
console.log("Bookmark Retrieved")
}
// RETRIEVE ACCESS TOKEN
token = await bookmark.access()
url = token.url
// PERFORM AN ACTION WITH THE URL
console.log("URL Path:", url.path)
if(Device.current.type === DeviceType.mac){
url.open()
}
}
catch(err){
if(!err.causedByUserCancelling){
console.error(err.name, err.message)
new Alert(err.name, err.message).show()
}
}
});
action.validate = function(selection, sender){
return true
};
return action;
})();
Public Folder Example Plug-In
The following plug-in is designed to provide access to write data to your Public folder, which can be shared with other team members on a local network. The example demonstrates how to write a text file to the Drop Box folder within the Public folder.
Bookmark Public Folder
/*{
"type": "action",
"targets": ["omnigraffle","omnifocus","omniplan","omnioutliner"],
"author": "Otto Automator",
"identifier": "com.omni-automation.all.public-folder-bookmark",
"version": "1.2",
"description": "This plug-in uses the URL.Bookmark class to create and retrieve stored bookmark for accessing the user’s Public folder.",
"label": "Public Folder",
"shortLabel": "Public Folder",
"paletteLabel": "Public Folder",
"image": "bookmark.square"
}*/
(() => {
credentials = new Credentials()
serviceTitle = "public-folder"
const action = new PlugIn.Action(async function(selection, sender){
try {
// TO REMOVE BOOKMARK HOLD DOWN CONTROL KEY WHEN SELECTING PLUG-IN
if (app.controlKeyDown){
alertMessage = "Remove the stored bookmark?"
alert = new Alert("Confirmation Required", alertMessage)
alert.addOption("Remove")
alert.addOption("Cancel")
alert.show(buttonIndex => {
if (buttonIndex === 0){credentials.remove(serviceTitle)}
})
console.log("Bookmark Removed")
return "Bookmark Removed"
} else {
// RETRIEVE BOOKMARK
bookmark = credentials.readBookmark(serviceTitle)
// IF NO BOOKMARK, ASK FOR FOLDER
if(!bookmark){
picker = new FilePicker()
picker.folders = true
picker.multiple = false
home = URL.documentsDirectory.path.split("/")[2]
picker.message = `Select “${home} ▶ Public” folder`
chosenDirectoryURLs = await picker.show()
bookmark = URL.Bookmark.fromURL(chosenDirectoryURLs[0])
credentials.writeBookmark(serviceTitle, bookmark)
bookmark = credentials.readBookmark(serviceTitle)
}
console.log("Bookmark Retrieved")
}
// RETRIEVE ACCESS TOKEN
token = await bookmark.access()
folderURL = token.url
// PERFORM AN ACTION WITH THE URL (WRITE TEXT FILE)
// Add a sub-folder to the Public Folder url:
folderURL = folderURL.appendingPathComponent("Drop Box")
fileName = "Test.txt"
fileURL = folderURL.appendingPathComponent(fileName)
dataObjStr = "This is a test file."
data = Data.fromString(dataObjStr)
wrapper = FileWrapper.withContents(fileName, data)
wrapper.write(fileURL, [FileWrapper.WritingOptions.Atomic], null)
if(app.platformName === "macOS"){
folderURL.open()
}
}
catch(err){
if(!err.causedByUserCancelling){
console.error(err.name, err.message)
new Alert(err.name, err.message).show()
}
}
});
action.validate = function(selection, sender){
return true
};
return action;
})();