Admin-only restricted metadata plugin for Kitsu / Zou.
This plugin adds private, project-scoped metadata columns for:
- Episodes
- Sequences
- Shots
- Assets
The metadata is stored in separate plugin database tables and does not appear in the standard Kitsu metadata panels.
Only Kitsu Admin users can access the plugin.
-
Admin-only access
-
Project-specific restricted metadata columns
-
Spreadsheet-style editing
-
Episode, Sequence, Shot and Asset tabs
-
Film and TV / episodic project support
-
Lazy-loaded tabs and groups
-
Collapsible grouped sections
-
Empty groups are hidden
-
Kitsu-style table layout and internal scrolling
-
Row selection and group selection
-
Editing one selected row mirrors the edit to other selected rows
-
CSV export with correct hierarchy per active tab
-
JSON export
-
Formula columns with calculated results
-
Formula results included in API row responses and CSV export
-
Supported field types:
- Text
- Number
- Checkbox
- List of values
- List of tags
- Checklist
- Formula
Sequences are shown directly.
Shots are grouped as:
Sequence
└── Shot
Assets are grouped as:
Asset Type
└── Asset
Sequences are grouped as:
Episode
└── Sequence
Shots are grouped as:
Episode
└── Sequence
└── Shot
Assets are grouped as:
Main Pack
└── Asset Type
└── Asset
Episode
└── Asset Type
└── Asset
Formula columns are read-only calculated columns.
The formula definition is stored in the plugin field configuration, but formula results are not stored as static database values. Results are calculated dynamically whenever rows are requested or CSV exports are generated.
This prevents stale calculated values if referenced cells are changed later.
Reference other columns using square brackets:
[Column Name]
Examples:
[Cost] * [Days]
[Area] ^ 2
[Price] * 10%
[Subtotal] + [Tax]
[Total] + [Another Formula Column]
+
-
*
/
^
()
%
[Price] * 10%
is treated as:
[Price] * 0.10
Checkbox columns can be used in formulas.
Checked = 1
Unchecked = 0
Formula columns can reference other formula columns.
Circular references are blocked and display:
ERROR
These column types cannot be used inside formulas:
List of tags
Checklist
Text and List of values columns can be used only if the cell value is numeric.
If a formula is invalid, the cell displays:
ERROR
You need:
- A working Kitsu / Zou server
- Shell access to the server
- The Zou virtual environment, usually:
/opt/zou/zouenv- The Zou CLI available at:
/opt/zou/zouenv/bin/zou- The PostgreSQL database password used by Zou
In the examples below, replace:
YOUR_DB_PASSWORDwith your own Zou database password.
SSH into the server where Zou is installed.
Example:
ssh ubuntu@YOUR-SERVER-IPsudo apt update
sudo apt install -y git zipcd ~
git clone https://github.com/PeteDraper/kitsu-restricted-metadata.git
cd kitsu-restricted-metadata. /opt/zou/zouenv/bin/activateYour prompt should now show something like:
(zouenv) ubuntu@ubuntu:~/kitsu-restricted-metadata$sudo mkdir -p /opt/zou/plugins
sudo chown -R ubuntu:ubuntu /opt/zou/pluginsIf your Linux username is not ubuntu, replace ubuntu:ubuntu with your username.
Example:
sudo chown -R myuser:myuser /opt/zou/pluginscd ~/kitsu-restricted-metadata
rm -rf plugins
rm -f /tmp/restricted-metadata.zip
zip -r /tmp/restricted-metadata.zip . \
-x ".git/*" \
-x "plugins/*" \
-x "__pycache__/*"Replace YOUR_DB_PASSWORD with your real Zou database password.
cd /opt/zou
DB_PASSWORD=YOUR_DB_PASSWORD \
/opt/zou/zouenv/bin/zou install-plugin \
--path /tmp/restricted-metadata.zip \
--forceExample:
cd /opt/zou
DB_PASSWORD=zC4LdTmrz9dM \
/opt/zou/zouenv/bin/zou install-plugin \
--path /tmp/restricted-metadata.zip \
--forceA successful install should show routes similar to:
/plugins/restricted-metadata/health
/plugins/restricted-metadata/context
/plugins/restricted-metadata/columns
/plugins/restricted-metadata/columns/<column_id>
/plugins/restricted-metadata/groups/episodes
/plugins/restricted-metadata/groups/sequences
/plugins/restricted-metadata/groups/shot-episodes
/plugins/restricted-metadata/groups/asset-types
/plugins/restricted-metadata/groups/asset-packs
/plugins/restricted-metadata/rows/episodes
/plugins/restricted-metadata/rows/sequences
/plugins/restricted-metadata/rows/shots
/plugins/restricted-metadata/rows/assets
/plugins/restricted-metadata/cell
/plugins/restricted-metadata/bulk-set
/plugins/restricted-metadata/asset-types
/plugins/restricted-metadata/export/json
/plugins/restricted-metadata/export/csv
/plugins/restricted-metadata/frontend
/plugins/restricted-metadata/frontend/<path:filename>
sudo systemctl restart zoumacOS:
Cmd + Shift + R
Windows / Linux:
Ctrl + Shift + R
Run:
curl http://127.0.0.1:5000/plugins/restricted-metadata/healthIf you are not authenticated, this should return a JWT warning such as:
{"msg":"Missing JWT in cookies or headers"}That is expected. It means the route exists and is protected.
Log in as an Admin user.
Open a project.
You should see the plugin entry in the Kitsu plugin menu.
Open:
Restricted Metadata
Available tabs:
- Episodes
- Sequences
- Shots
- Assets
If the project does not use Episodes, the Episode tab is hidden.
Click:
Manage Columns
Enter:
Column name
Choose a type:
Text
Number
Checkbox
List of values
List of tags
Checklist
Formula
For these field types, enter comma-separated options:
List of values
List of tags
Checklist
Example:
Low, Medium, High
For Formula, enter the formula expression into the Options / Formula field.
Example:
[Cost] * [Days]
Click:
Create Column
The column appears in the current entity table.
Each row has its own private value for each restricted metadata column.
Example:
Shot 001 | Vendor Grade = A
Shot 002 | Vendor Grade = B
Shot 003 | Vendor Grade = C
Select multiple rows using the row checkboxes.
Then edit one selected row.
The same value is applied to all selected rows.
Group rows also have checkboxes:
- In Shots on non-episodic projects, selecting a Sequence group selects all loaded shots in that sequence.
- In Shots on episodic projects, selecting a Sequence group inside an Episode selects all loaded shots in that sequence.
- In Sequences on episodic projects, selecting an Episode group selects all loaded sequences in that episode.
- In Assets on non-episodic projects, selecting an Asset Type group selects all loaded assets in that asset type.
- In Assets on episodic projects, selecting an Asset Type group inside Main Pack or an Episode selects all loaded assets in that asset type.
Selections remain active until manually deselected.
Click:
Export CSV
CSV export follows the active tab and the project structure.
Episodes:
Episode,<custom columns>
Sequences:
Episode,Sequence,<custom columns>
Shots:
Episode,Sequence,Shot,<custom columns>
Assets:
Episode / Main Pack,Asset Type,Asset,<custom columns>
Sequences:
Sequence,<custom columns>
Shots:
Sequence,Shot,<custom columns>
Assets:
Asset Type,Asset,<custom columns>
Formula results are included in CSV exports.
CSV export:
/api/plugins/restricted-metadata/export/csv?production_id=PROJECT_ID&entity_type=shot
JSON export:
/api/plugins/restricted-metadata/export/json?production_id=PROJECT_ID
Valid CSV entity_type values:
episode
sequence
shot
asset
To update to the latest GitHub version:
cd ~/kitsu-restricted-metadata
git pull origin mainRebuild the zip:
rm -rf plugins
rm -f /tmp/restricted-metadata.zip
zip -r /tmp/restricted-metadata.zip . \
-x ".git/*" \
-x "plugins/*" \
-x "__pycache__/*"Reinstall:
cd /opt/zou
DB_PASSWORD=YOUR_DB_PASSWORD \
/opt/zou/zouenv/bin/zou install-plugin \
--path /tmp/restricted-metadata.zip \
--forceRestart Zou:
sudo systemctl restart zouHard refresh Kitsu in your browser:
Cmd + Shift + R
or on Windows/Linux:
Ctrl + Shift + R
After making local changes:
cd ~/kitsu-restricted-metadata
git status
git add -A
git commit -m "Update restricted metadata plugin"
git push origin mainOptional release tag:
git tag -a v0.3.0 -m "Nested groups formulas CSV export and UI refinements"
git push origin v0.3.0This is normal when testing with curl:
{"msg":"Missing JWT in cookies or headers"}It means the plugin route exists and is protected.
Restart Zou:
sudo systemctl restart zouCheck the service:
sudo systemctl status zou --no-pagerCheck logs:
sudo journalctl -u zou -n 120 --no-pagerCheck that the frontend route was registered during installation:
/plugins/restricted-metadata/frontend
/plugins/restricted-metadata/frontend/<path:filename>
If not, rebuild and reinstall the zip.
If installation or testing fails with:
password authentication failed
make sure you are passing the database password:
DB_PASSWORD=YOUR_DB_PASSWORD /opt/zou/zouenv/bin/zou install-plugin --path /tmp/restricted-metadata.zip --forceOlder development versions used:
multi_select
The current version uses:
checklist
To convert old columns:
cd /opt/zou
DB_PASSWORD=YOUR_DB_PASSWORD /opt/zou/zouenv/bin/python - <<'PY'
from zou.app import app, db
from sqlalchemy import text
with app.app_context():
db.session.execute(text("""
UPDATE plugin_restricted_metadata_fields
SET field_type = 'checklist'
WHERE field_type = 'multi_select'
"""))
db.session.commit()
print("Converted multi_select columns to checklist")
PYRestart Zou afterwards:
sudo systemctl restart zouCheck the formula syntax.
Valid examples:
[Cost] * [Days]
[Area] ^ 2
[Price] * 10%
[Subtotal] + [Tax]
Common causes of ERROR:
- Referenced column does not exist
- Referenced text value is not numeric
- Referenced List of values entry is not numeric
- Formula references a Tags column
- Formula references a Checklist column
- Formula has a circular reference
- Formula syntax is invalid
The plugin stores restricted metadata in separate plugin tables:
plugin_restricted_metadata_fields
plugin_restricted_metadata_values
Formula definitions are stored in field configuration.
Formula results are calculated dynamically.
Formula results are not written as static cell values.
The plugin does not store restricted values in Kitsu’s standard custom metadata descriptors.
This is intentional because Kitsu’s normal metadata is visible through standard Kitsu entity pages and APIs, while this plugin is designed for Admin-only sensitive metadata.
This plugin is Admin-only.
All backend routes call Zou’s admin permission check before returning or changing data.
Do not use this plugin for non-admin access until role-based permissions have been intentionally added and tested.