Plugin anatomy
The smallest useful map of an Oruva plugin folder.
my.asset-tool/
├── plugin.json ← manifest (required, UTF-8, max 64 KiB, schema_version 2)
├── main.py ← entry program (any name; declared in the manifest)
├── ui.html ← optional action interface
└── icon.png ← optional icon (plugin-wide; actions may add their own)
Rules that trip people up:
- The folder name must match the manifest
id. The discovery comparison is case-insensitive; plugin IDs themselves are lowercase by schema. entry,icon, actionicon, and actionuipaths must resolve inside the plugin folder. Absolute paths,..traversal, and symlinked escapes are rejected — and the folder may not contain symbolic links at all, because approval hashes every file in it.- Unknown manifest fields are errors. This is deliberate: it keeps
plugin.jsonforward-compatible (new capabilities arrive as new optional fields in new app versions, never as silently ignored typos). - The folder is limited to 4096 files and 256 MiB for approval hashing.