Phials plugin documentation
User guide
AI Disclosure: This page was generated by an LLM and may contain inaccuracies. Hand-crafted documentation will be implemented over time on the road to 1.0

Permission-gated Plugin API operations

This page maps typed public operations to manifest permissions. Prefer these typed services over api.invoke; the typed API owns argument shapes, result types, plugin scoping, and cleanup.

Always-available operations

Operations marked None require no manifest permission. They remain limited to their documented scope: a user choice, plugin-owned data, read-only app context, an activated provider, or host-owned feedback. They do not grant general filesystem, clipboard, network, or host-command access.

File operations

OperationPermissionResult or consequence
api.files.getExtension(filename)NoneLowercase extension without the period, or ""
api.files.getBasename(path)NoneLast path segment
api.files.getDirname(path)NoneParent path
api.files.joinPath(...parts)NoneJoined portable path string
api.files.pickDirectory(options?)NoneUser-selected path or null
api.explorer.getActivePane() / getPane(id)NoneExplicitly acquires a reactive Public Explorer pane facade
pane.navigation.openPath(path)NoneOpens through the exact pane’s supported primary Phials action
api.files.revealPath(path)NoneReveals the path in the native file manager
api.files.readDirectory(path)filesystem.read or filesystem.writeEntries plus ordered child-materialization failures
api.files.toAssetUrl(path)filesystem.read or filesystem.writeTrusted-renderer asset URL for one absolute file path
api.files.readBinary(path)filesystem.read or filesystem.writeRaw-byte snapshot plus opaque revision
api.files.getFolderSummary(path, { signal })filesystem.read or filesystem.writeCancellable recursive counts and byte total
api.git.getInfo(path) / getLanguages(path)filesystem.read or filesystem.writeFixed read-only repository projections with sanitized remotes
api.files.readText(path)filesystem.read or filesystem.writePluginTextFileSnapshot with content and opaque revision
api.files.watchDirectory(path, handler)filesystem.read or filesystem.writePluginDirectoryWatch; unsubscribe() releases it

MetadataProvider.extract receives target-bound api.readFile() and api.readTextFile() methods that require no filesystem permission. They accept no path and expire with the extraction callback. Reading any other file uses the permission-gated api.files methods above. | api.files.writeText(path, content, options) | filesystem.write | PluginTextWriteResult: saved revision or conflict | | api.files.createDirectory(path) | filesystem.write | Creates one directory | | api.files.renamePath(source, destination) | filesystem.write | Renames within one directory | | api.files.writeBinary(path, content, options) | filesystem.write | Atomic saved-or-conflict result using the shared revision contract | | api.files.trash(paths) | filesystem.write | Ordered per-path success/failure outcomes |

filesystem.write implies supported reads. pickDirectory is always available because the user chooses a path; reading the selected directory or its files is separately gated.

Clipboard and network

OperationPermissionResult
api.clipboard.readText()clipboard.readCurrent clipboard text
api.clipboard.writeText(text)clipboard.writevoid after replacement
api.fetch(input, init?)network.fetchStandard Response

Clipboard permissions do not imply each other. network.fetch gates only the supported Plugin API wrapper; it is not a renderer network sandbox.

Workspace Folder operations

Operation groupPermissionResult
api.workspaceFolders schema, value, tag, rating, known-folder, and existing-Page readsworkspace-folders.read or workspace-folders.writeTyped immutable Workspace Folder projections
api.workspaceFolders property, tag, rating, and schema mutationsworkspace-folders.writeValidated atomic changes
api.workspaceFolders.openPage with implicit creationworkspace-folders.writeHost-mediated confirmation, creation, reconciliation, and opening

workspace-folders.write implies protected reads. Do not pair it with workspace-folders.read.

Provider-scoped helpers

These operations are always available only in the provider callback or surface scope that declares them:

OperationManifest permissionScope
MetadataAPI.readFile()NoneReads only the exact host-selected extraction target as Uint8Array
MetadataAPI.readTextFile()NoneReads only the exact host-selected extraction target as UTF-8 text
PreviewAPI.getMetadata(file)NonePreview-specific factories receiving PreviewAPI
PreviewAPI.openFullscreen(file)NonePreview-specific factories receiving PreviewAPI
PreviewAPI.navigateTo(path)NonePreview-specific factories receiving PreviewAPI
FileMatchAPI.matchesExtension(file, extensions)NoneProvider matching callbacks receiving FileMatchAPI
FileMatchAPI.matchesMime(file, mimeTypes)NoneProvider matching callbacks receiving FileMatchAPI
FileMatchAPI.matchesCategory(file, categories)NoneProvider matching callbacks receiving FileMatchAPI

Do not retain a specialized API beyond its documented lifetime or cast a base PluginAPI to obtain it. Phials invalidates retained base, Preview, and Metadata API objects when that activation deactivates.

Plugin-owned data

Plugin-owned settings and data are namespaced by the activated plugin ID and do not require manifest permissions:

ServiceAlways-available operations
api.settingsget, set, getAll
api.storageget, set, delete, keys, clear
api.databasequery, execute, insert, update, deleteFrom, selectAll for declared plugin tables

api.database throws when the exported PhialsPlugin has no database schema. Manifest permissions do not expand a plugin beyond its own settings namespace, storage namespace, or declared database tables.

App context, panels, events, and feedback

These base Plugin API operations require no manifest permission:

ServiceAlways-available operations
api.appSettingsRead thumbnailsEnabled, thumbnailSize, thumbnailQuality, showHiddenFiles, and showParentDirectory
api.modulesopenCenter(moduleProviderId, state, options?) for an activated center-capable ModuleProvider
api.eventson, once, emit, register; subscriptions remain subject to lifecycle cleanup
api.modalconfirm, prompt, alert, choose
api.notifyinfo, success, warning, error

No permission makes an unknown module provider, event, database table, or app setting available.

Approved host commands

api.invoke performs two checks:

  1. the command name must be in the community-plugin allowlist; and
  2. the current manifest permission set must include the command’s required permission, when any.

An allowed name can still fail because of invalid arguments, an unavailable tool, an unsupported platform condition, a missing path, or operating-system access rules.

See Approved host command reference for the complete command-by-command mapping. A permission never authorizes a host command absent from that table.